Главная > Технический изврат > Чиним отображение курсов валют в IP телефонах Grandstream [ОБНОВЛЕНО]

Чиним отображение курсов валют в IP телефонах Grandstream [ОБНОВЛЕНО]

Над моим рабочим столом висит телефон Grandstream GXP2110. Достаточно удобная и беспроблемная модель. На экране можно просматривать погоду (достаточно точно и правильно) и курсы валют. И вот эти самые курсы внезапно перестали отображаться.

Пришлось взять в руки tcpdump и посмотреть, откуда телефон берет эти данные. Оказалось, что он шлет запросы типа:
GET http://download.finance.yahoo.com/d/333.txt?s=BTCUSD=X&s=EURUSD=X&s=USDRUB=X&s=EURRUB=X&s=CNYRUB=X&f=l1s
И получает в ответ 404 Not Found. Исправить адрес в настройках нет никакой возможности.

Некоторое время я ждал, что производитель как-нибудь на это отреагирует и поправит прошивку, но этого так и не случилось. Сегодня я зашел на сайт за новой версией прошивки и обнаружил, что модель снята с поддержки, а проблема так и не решена. Значит, пришло время подставлять костыль.

Из множества вариантов подмены адреса я выбрал самый простой – использовать прокси. Под рукой имелся тестовый веб-сервер с nginx. Хотя то же самое можно было бы провернуть с apache или squid.

В расширенных сетевых настройках телефона я задал HTTP proxy = server_address:8000 и убедился, что запросы уходят куда надо. Кстати, эта настройка применяется только после перезагрузки телефона.

Конфигурационный файл nginx:

server {
  listen 8000;
  access_log /var/log/nginx/proxy.access.log main;
  error_log /var/log/nginx/proxy.error.log notice;
  
  # для погоды
  location /forecastrss {
    proxy_pass http://xml.weather.yahoo.com/forecastrss;
  }

  # для валют
  location /d/333.txt {
    proxy_pass http://localhost/grandstream/currency.php;
  }
}

Файл currency.php:

<?php 
$url = 'http://download.finance.yahoo.com/d/quotes.csv?'; 
$pairs = array(); 
$f = ""; 

$params = preg_split('/&/', $_SERVER['QUERY_STRING']); 
foreach ($params as $param) { 
  if (preg_match('/^s=/', $param)) $pairs[] = $param; 
  elseif (preg_match('/^f=/', $param)) $f = $param; 
} 

foreach ($pairs as $pair) { 
  echo file_get_contents($url . $pair . '&' . $f); 
} 
?>

И все завертелось! Конечно, это не самое оптимальное, но вполне работоспособное решение. Одним словом, костыль. Если кто-нибудь напишет что-нибудь более интересное на эту тему, обязательно посмотрю, а может, и использую.

UPDATE:
После более месяца успешной работы оказалось, что провайдер почему-то забанил адрес, по которому я получал данные. Пришлось добавить в скрипт поддержку прокси и заодно ускорить работу путем параллельной обработки запросов.

UPDATE 2: Добавлена поддержка округления курса, потому что на телефоне помещается максимум 8-9 знаков и обрезаются первые цифры.

<?php

$url = 'http://download.finance.yahoo.com/d/quotes.csv?';
$proxy_addr = 'addr:port';
$proxy_user = 'user:password';
$round = 2;

$pairs = array();
$f = "";

$params = preg_split('/&/', $_SERVER['QUERY_STRING']);

foreach ($params as $param) {
   if (preg_match('/^s=/', $param)) $pairs[] = $param;
   elseif (preg_match('/^f=/', $param)) $f = $param;
}

$cm = curl_multi_init();
$cmh = array();

foreach ($pairs as $pair) {
   $h = curl_setup($url . $pair . '&' . $f);
   curl_multi_add_handle($cm, $h);
   $cmh[] = $h;
}

$running = false;
do {
   curl_multi_exec($cm, $running);
   curl_multi_select($cm);
} while ($running);

foreach($cmh as $h) {
   $content = curl_multi_getcontent($h);
   if ($round) {
      list($rate, $name) = explode(',', $content, 2);
      $rate = round((float)$rate, $round);
      echo "${rate},${name} ";
   } else {
      echo $content;
   }

   curl_multi_remove_handle($cm, $h);
}

curl_multi_close($cm);

// ===

function curl_setup($url)
{
   global $proxy_addr, $proxy_user;
   $h = curl_init($url);
   curl_setopt($h, CURLOPT_RETURNTRANSFER, true);
   curl_setopt($h, CURLOPT_HEADER, false);
   curl_setopt($h, CURLOPT_TIMEOUT, 10);
   if ($proxy_addr) curl_setopt($h, CURLOPT_PROXY, $proxy_addr);
   if ($proxy_user) curl_setopt($h, CURLOPT_USERPWD, $proxy_user);
   return $h;
}
?>
  1. Пока что нет комментариев.

*