Введение

Over The Air Provision (OTAP)  TC65Т

GSM модем SL116 на базе модуля Enfora GSM0308

Пишите автору сайта ganatol2000@mail.ru

Программа просмотра данных, переданных модемом TC65, с использованием веб интерфейса.

 Основным результатом работы программы сервера, принимающей UDP сообщения от модема, есть данные которые сохраняются в базу организованную на MySQL.


Рис.1


Программа просмотра данных должна:
 - отображать последнее значение контролируемого сигнала, получаемого с аналоговых входов AI0 и AI1, и время поступления этого значения для  каждого модема.
- при необходимости изобразить изменения аналогового сигнала за заданный период времени в виде графика.
 Просмотр данных мы организуем с использованием веб интерфейса т. е. пользователю для работы достаточно иметь лишь веб - браузер.
 Наша же задача написать программу для веб - сервера, которая будет формировать соответствующий
html-код. Для этого будет задействован такой инструмент как PHP  отлично работающий с MySQL, а для построения графиков можно использовать специальную библиотеку JPGraph, тоже работающую на основе PHP.
 Как скачать и установить
PHP на веб сервер IIS, входящий в Windows или на веб сервер Apache надеюсь разберетесь. Напомню только, что возможно придется немного отредактировать файл php.ini и в настройках  web-сервера необходимо прописать обработку расширения php файлом php-cgi.exe. Чтобы добраться до этой настойки в IIS следует запустить Internet Information Services из папки Администрирование (Настройки - Панель управления), потом выбираем правой кнопкой мыши Веб-узлы далее Свойства, и сначала кликнем вкладку Домашний каталог затем нажимаем кнопку Настройка.

Можно  скачать и установить
Денвер — набор дистрибутивов (Apache, PHP, MySQL, Perl и т.д.).
  Программа будет состоять из трех файлов WebWatchTC65
Table.php, WebWatchTC65unit.php, WebWatchTC65Graph.php. Они должны располагаться в корневом каталоге веб сервера. Пользователь в  браузере должен набрать примерно следующее: http://213.33.999.999/WebWatchTC65.php
 Работает программа с базой данных представленной на Рис.1.

Файл WebWatchTC65.php
Вначале здесь посредством SQL-запроса определяется количество модемов, информация от которых присутствует в базе данных, и определяются идентификаторы этих модемов. Затем генерируется запрос на предмет определения времени поступления последней информации от каждого модема и в заключении извлекаются данные, соответствующие этому времени. Отображение данных будет оформлено в виде таблицы, для этого необходимо сформировать соответствующий html-код.

<HTML>
<meta http-equiv="Content-type" content="text/html; charset=windows-1251">
Этот тег командует перезагружать страницу каждые 20 секунд, чтобы отображаемые данные регулярно обновлялись.
<meta http-equiv="refresh" content="20" >
Определяем цвет фона страницы.
<BODY BGCOLOR="#CCFFCC"></BODY>

<?php
//Из базы данных определяем количество идентификаторов модемов. Инструкция DISTINCT устраняет повторения в отсортированном результате SQL запроса
$db=mysql_connect("localhost", "alex", "12345");
mysql_select_db("tc65t",$db);
mysql_query("set names cp1251");
$result=mysql_query("SELECT DISTINCT id FROM tc65tdbnew ORDER BY id",$db);
//Создадим массив и заполним его списком идентификаторов модемов, который получили в SQL запросе.
$IdDB=array();
$myrow=mysql_fetch_array($result);
do{
array_push($IdDB,$myrow['id']);
}while($myrow=mysql_fetch_array($result));
//Определяем количество элементов в массиве, а значит и количество модемов.
$count=count($IdDB);

//Дальнейшие действия имеют смысл, если есть данные хотя бы от одного модема.
if($count>0)
{
//Создадим массив и заполним его значениями  времени,  которые соответствуют последним поступившим данным от каждого модема
$MaxTimeDB=array();
for($i=0; $i<$count; $i++)
{
$result_max_time=mysql_query("SELECT MAX(Time) FROM tc65tdbnew WHERE id='$IdDB[$i]'",$db);
$row_max_time=mysql_fetch_array($result_max_time);
do{
array_push($MaxTimeDB,$row_max_time['MAX(Time)']);
//echo $MaxTimeDB[$i]."<br>";
}while($row_max_time=mysql_fetch_array($result_max_time));
}

//Создадим массивы с данными аналоговых сигналов соответствующих  времени последнего поступления UDP сообщения для каждого модема.
$AI0DB=array();
$AI1DB=array();
for($i=0; $i<$count; $i++)
{
$result_end=mysql_query("SELECT * FROM tc65tdbnew WHERE id='$IdDB[$i]' and Time='$MaxTimeDB[$i]'",$db);
$myrow_end=mysql_fetch_array($result_end);
do{
array_push($AI0DB,$myrow_end['AI0']);
array_push($AI1DB,$myrow_end['AI1']);
//echo $myrow_end['AI0']." ".$myrow_end['AI1']."<br>";
}while($myrow_end=mysql_fetch_array($result_end));
}

//Время в UNIX формате требуется представить в виде более привычным человеку. К счастью в php есть класс DateTime и функции этого класса решают нашу проблему. Из массива со значениями времени в формате UNIX cоздадим массив со значениями времени в формате DateTime.
$Time=array();
for($i=0; $i<count($MaxTimeDB); $i++)
{
$date = date_create();
date_timestamp_set($date, $MaxTimeDB[$i]+1000000000);
array_push($Time,date_format($date, 'Y-m-d H:i:s'));
}

//В таблице мы должны предусмотреть кнопку, которая  будет вызывать окно формирующее в последующем график. Организовано это посредством JScript перехватывающего событие кнопки onclick и вызывающего функцию OpenWin().
$StrButton1="<BUTTON align=\"center\" onclick = \"OpenWin(";
$StrButton2=")\">Подробно</BUTTOM>";

//Формируем таблицу с данными модемов.
В ячейках с числовыми значениями изменим размер шрифта.

Откорректируем также цвет шрифта и фона.
echo"<TABLE BORDER=10 ID=\"mytab\" align=\"center\">";
echo"<CAPTION ALIGN=TOP><h2><font size=\"5\"; color=\"Red\">Величина сигналов на аналоговых входах модема</font></h2></САРТION>";
echo"<TH BGCOLOR=\"WHITE\">ID</TH><TH BGCOLOR=\"WHITE\">AI0</TH><TH BGCOLOR=\"WHITE\">AI1</TH><TH BGCOLOR=\"WHITE\">Time</TH><TH BGCOLOR=\"WHITE\">График</TH>";
for($i=0; $i<$count; $i++)
{
echo"<tr ID=\"".$IdDB[$i]."\"".">";
echo"<td BGCOLOR=\"WHITE\">"."<font size=\"4\"; color=\"Blue\">".$IdDB[$i]."</font>"."</td>".
"<td BGCOLOR=\"WHITE\">"."<font size=\"4\"; color=\"Blue\">".$AI0DB[$i]."</font>"."</td>".
"<td BGCOLOR=\"WHITE\">"."<font size=\"4\"; color=\"Blue\">".$AI1DB[$i]."</font>"."</td>".
"<td BGCOLOR=\"WHITE\">"."<font size=\"4\"; color=\"Blue\">".$Time[$i]."</font>"."</td>".
"<td BGCOLOR=\"WHITE\">".$StrButton1.$IdDB[$i].$StrButton2."</td>";
echo"</tr>";
}
echo"</TABLE>";
}
//if($count>0)
?>
//JScript представлен функцией OpenWin(a) в качестве параметра принимающей идентификатор модема. Для создания нового окна в ней используется функция window.open( адрес файла,  имя окна,  параметры). Здесь адрес файла формируется с GET запросом, для чего и нужен идентификатор модема. Здесь имя окна представлено как "_blank", т. к. нам нужно, чтобы всегда при нажатии на кнопку создавалось новое окно. Со строкой параметры все ясно без пояснений.
<script>
function OpenWin(a)
{

strfeatures = "top=100,left=15,width=450, height=320, location=no, menubar=no, resizable=yes, toolbar=yes"
strWebWatch="WebWatchTC65Unit.php?ID="+a
window.open(strWebWatch, "_blank", strfeatures);
}
</script>

</HTML>

 


Файл
WebWatchTC65unit.php
Этот php-скрипт выполняется со своим параметром GET запроса, в качестве которого используется номер идентификатора модема.  Страница будет состоять из двух частей. В верхней части на сером фоне вовсю длину экрана будет отображаться значение идентификатора модема, а также дата и время поступления текущей информации. Ниже на поле горчичного фона будут располагаться цифры текущих значений аналоговых сигналов на входах модема AI0 и AI1. Там же будет располагаться форма с полями выбора(SELECT) и кнопкой, используемая при построении графика .
<HTML>
<meta http-equiv="Content-type" content="text/html; charset=windows-1251" />
Определяем цвет фона страницы
<BODY BGCOLOR="#CCFFCC"></BODY>
Задаем таблицу стилей. Для каждой части страницы определяем свой стиль состоящий из цвета фона и шрифта, размеров поля, места расположения на странице.
<style type="text/css">
 #ID {
position: relative;
background: #ccc;
padding: 5px;
padding-right: 20px;
border: solid 1px black;
text-align: center;
font-size: large;
color: Green
}
#AI {
//Расположим блок в центре.
position: relative;
left:50%;
margin-left:-110px;
width: 220px;

height:200px;
background:#fc0;
font-size: medium;
color: Blue
}
</style>


<?php
//Получаем значение GET запроса
$IDmodem=$_GET['ID'];
//Смысл дальнейших действий - это генерация html-кода формы предназначенной для обмена данными с сервером. Форма устанавливается тегом FORM. Атрибут ACTION будет указывать на php-скрипт  WebWatchTC65Graph.php, который отвечает за построение графика.  На форме будут располагаться элементы интерфейса в виде раскрывающегося списка (тег SELECT) для выбора  даты начала и даты конца построения графика и кнопка методом GET отправляющая эту информацию на сервер.

//Список годов создается динамически. Текущий год определяется функцией date("Y") Следующая php-функция создает строку тегов option такого вида:
<option value="1999">1999</option>
<option value="2000">2000</option>
<option value="2001">2001</option> и т. д. до текущего года.
function GetListYear()
{
$ListYear="";
for($i=1999; $i<date("Y"); $i++)
{
$ListYear=$ListYear."<option value=\"".$i."\">".$i."</option>";
}
$ListYear=$ListYear."<option selected value=\"".date("Y")."\">".date("Y")."</option>";
return $ListYear;
}

//Список чисел дней месяца от 1 до 31 создадим динамически. При помощи JScript он будет корректироваться в зависимости от выбранного месяца и года.
function GetListDay()
{
$ListDay="";
for($i=1; $i<32; $i++)
{
$ListDay=$ListDay."<option value=\"".$i."\">".$i."</option>";
}
return $ListDay;
}

$MyListYear=GetListYear();
$MyListDay=GetListDay();

//В переменной $html_buttonAI задается html-код формы (тег <FORM>...</FORM>) задающей условия для построение графиков аналоговых сигналов  модема за заданный период времени и посылающей команду на выполнение. Кроме списков выбора даты и кнопки на форме присутствует скрытое поле: ID (идентификатор модема) со значением полученным по GET запросу. В форме используется  Java-скрипты rewrite_days_begin() и rewrite_days_end().
JScript rewrite_days_begin() вызывается при изменении в списке выбора месяца или в списке выбора года относящихся к дате начала построения графика, а JScript rewrite_days_end() вызывается при изменении в аналогичных списках относящихся к дате конца построения графика. Эти Java-скрипты корректируют списки выбора даты таким образом, чтобы там присутствовали только числа соответствующие выбранному месяцу и году.
$html_buttonAI="<FORM ACTION=\"WebWatchTC65Graph.php\" METHOD=\"GET\">
<INPUT TYPE=HIDDEN name=\"ID\" id=\"ID\" value=\"".$IDmodem."\">
<select name=\"day_begin\" id=\"day_begin\">".
$MyListDay.
"</select>
<select name=\"month_begin\" id=\"month_begin\" onChange=\"rewrite_days_begin();\">
<option value=\"1\">Январь</option>
<option value=\"2\">Февраль</option>
<option value=\"3\">Март</option>
<option value=\"4\">Апрель</option>
<option value=\"5\">Май</option>
<option value=\"6\">Июнь</option>
<option value=\"7\">Июль</option>
<option value=\"8\">Август</option>
<option value=\"9\">Сентябрь</option>
<option value=\"10\">Октябрь</option>
<option value=\"11\">Ноябрь</option>
<option value=\"12\">Декабрь</option>
</select>
<select name=\"year_begin\" id=\"year_begin\" onChange=\"rewrite_days_begin();\">".
$MyListYear.
"</select>
<select name=\"day_end\" id=\"day_end\">".
$MyListDay.
"</select>
<select name=\"month_end\" id=\"month_end\" onChange=\"rewrite_days_end();\">
<option value=\"1\">Январь</option>
<option value=\"2\">Февраль</option>
<option value=\"3\">Март</option>
<option value=\"4\">Апрель</option>
<option value=\"5\">Май</option>
<option value=\"6\">Июнь</option>
<option value=\"7\">Июль</option>
<option value=\"8\">Август</option>
<option value=\"9\">Сентябрь</option>
<option value=\"10\">Октябрь</option>
<option value=\"11\">Ноябрь</option>
<option selected value=\"12\">Декабрь</option>
</select>
<select name=\"year_end\" id=\"year_end\" onChange=\"rewrite_days_end();\">".
$MyListYear.
"</select>
<INPUT TYPE=\"Submit\" VALUE = \"График\">
</FORM>";


//Теперь посредством SQL запросов, зная идентификатор модема, определяем  время последнего поступления данных от модема и числовые значения сигналов на аналоговых входах модем в этот момент
$db=mysql_connect("localhost", "alex", "12345");
mysql_select_db("tc65t",$db);
mysql_query("set names cp1251");

//Применим здесь уже знакомый программный код SQL запросов и создания массивов, но в этом случае полученные массивы $MaxTimeDB, $AI0DB, $AI1DB, $Time будут состоять лишь из одного члена.
$MaxTimeDB=array();
$result_max_time=mysql_query("SELECT MAX(Time) FROM tc65tdbnew WHERE id='$IDmodem'",$db);
$row_max_time=mysql_fetch_array($result_max_time);
do{
array_push($MaxTimeDB,$row_max_time['MAX(Time)']);
//echo $MaxTimeDB[$i]."<br>";
}while($row_max_time=mysql_fetch_array($result_max_time));


$AI0DB=array();
$AI1DB=array();
for($i=0; $i<count($MaxTimeDB); $i++)
{
$result_end=mysql_query("SELECT * FROM tc65tdbnew WHERE id='$IDmodem' and Time='$MaxTimeDB[$i]'",$db);
$myrow_end=mysql_fetch_array($result_end);
do{
array_push($AI0DB,$myrow_end['AI0']);
array_push($AI1DB,$myrow_end['AI1']);
//echo $myrow_end['AI0']." ".$myrow_end['AI1']."<br>";
}while($myrow_end=mysql_fetch_array($result_end));
}


$Time=array();
for($i=0; $i<count($MaxTimeDB); $i++)
{
$date = date_create();
date_timestamp_set($date, $MaxTimeDB[$i]+1000000000);
array_push($Time,date_format($date, 'Y-m-d H:i:s'));
}

//Отображать числовые значения сигналов на аналоговых входах модема AI0 и AI1 будем в виде таблицы, но таблица будет без рамки с увеличенными расстояниями между ячейками.  Соответствующий   html-код сохраним в виде переменной.
$TableAI="<TABLE cellspacing=\"5\" cellpadding=\"10\" ID=\"mytab\" align=\"center\">
<TH><font size=\"4\"; color=\"Green\">AI0</TH></font><TH><font size=\"4\"; color=\"Green\">AI1</font></TH>".
"<tr>".
"<td><font size=\"4\"; color=\"Blue\">".$AI0DB[0]."</font></td>".
"<td><font size=\"4\"; color=\"Blue\">".$AI1DB[0]."</font></td>".
"</tr>".
"</TABLE>";

//Теперь отображаем два подготовленнах блока в окне браузера.
print "<div id=ID>"."ID модема="."<font size=\"5\" color=\"red\">".$IDmodem."</font>"."<br>"." ".
"дата:"."<font size=\"5\"; color=\"red\">".$Time[0]."</font>"."</div>";
print "<div id=AI align=center>".$TableAI.
"<br>".$html_buttonAI."</div>";

?>

//В JScript входят две однотипные функции корректирующие списки дней  в зависимости от выбранного месяца и года для даты начала и для даты окончания графика соответственно.
<script>
function rewrite_days_begin()
{
var days;
var month;
var year;
days=document.getElementById("day_begin");
month=document.getElementById("month_begin");
year=document.getElementById("year_begin");
var days_in_month=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
if((year.value % 4==0)&&(month.value==2))
{
days.length=29;
days.item(28).value=29;
days.item(28).text=29;
}
else
{
days.length=days_in_month[month.value-1];
for(var i=28; i<=days.length; i++)
{
days.item(i-1).value=i;
days.item(i-1).text=i;
}
}
}

function rewrite_days_end()
{
var days;
var month;
var year;
days=document.getElementById("day_end");
month=document.getElementById("month_end");
year=document.getElementById("year_end");
var days_in_month=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
if((year.value % 4==0)&&(month.value==2))
{
days.length=29;
days.item(28).value=29;
days.item(28).text=29;
}
else
{
days.length=days_in_month[month.value-1];
for(var i=28; i<=days.length; i++)
{
days.item(i-1).value=i;
days.item(i-1).text=i;
}
}
}
</script>

</HTML>


 

Файл WebWatchTC65Graph.php
Этот php-скрипт, используя библиотеку JPGraph, выполняет построение графика. Фактически график является PNG - картинкой. Чтобы на картинке русские буквы нормально отображались файл WebWatchTC65Graph.php должен быть в формате utf-8.
<?php
//Подключаем библиотеку JPGraph.
include ("JPGraph/jpgraph.php");
//Подключаем библиотеку JPGraph отвечающую за изображение графика в виде линии
include ("JPGraph/jpgraph_line.php");

//Эта функция выполняет построение графика. В качестве параметров принимает массивы значений сигналов на аналоговых входах модема AI0 и AI1, массив значений времени, а также идентификатор модема, чтобы использовать его в заголовке.
function graphDB($arrayAI0, $arrayAI1, $arrayDayTime, $IDmodem)
{
//Размер картинки будет 1000x440 пикселей
$graph = new Graph(1000, 440);
$traff0=$arrayAI0;
$traff1=$arrayAI1;
$daysTime=$arrayDayTime;
//Надпись в заголовке
$str="Измерение (мВ):"." ".$IDmodem."-ый модем";
//Устанавливаем систему счисления для оси абсцисс текстовую(используется только для оси абсцисс), а для оси ординат линейную.
$graph->SetScale( "textlin");

//Создаем линию графика значений сигнала на аналоговом входе AI0
//Линия будет строиться на основе массива $traff0
$lineplot0 =new LinePlot($traff0);
//Добавляем линию на график.
$graph->Add( $lineplot0);
//Устанавливаем тип, цвет и размер меток на линии
$lineplot0->mark->SetType(MARK_IMG_DIAMOND, 'blue', 0.3);
//Возле меток отображаем их числовое значение
$lineplot0->value->Show();
//Устанавливаем цвет чисел возле меток
$lineplot0->value->SetColor("blue");
//Шрифт чисел возле меток
$lineplot0->value->SetFont(FF_FONT0,FS_BOLD);
//Размер чисел
$lineplot0->value->SetFormat(" %01.0f");
//Устанавливаем цвет линии
$lineplot0 ->SetColor("blue");
//Используем легенду, чтобы было понятно график какого процесса отображает эта линия
$lineplot0->SetLegend('AI0');

//Создаем линию графика значений сигнала на аналоговом входе AI1
$lineplot1 =new LinePlot($traff1);
$graph->Add( $lineplot1);
$lineplot1->mark->SetType(MARK_IMG_SQUARE, 'red', 0.3);
$lineplot1->value->Show();
$lineplot1->value->SetColor("darkgray");
$lineplot1->value->SetFont(FF_FONT0,FS_BOLD);
$lineplot1->value->SetFormat(" %01.0f");
$lineplot1 ->SetColor("red");
$lineplot1->SetLegend('AI1');


//В качестве надписей на оси асцисс будут использоваться члены массива $daysTime
$graph->xaxis->SetTickLabels($daysTime);
//Отображаться будет каждая вторая надпись
$graph->xaxis->SetTextLabelInterval(2);
//Развернем надписи оси абсцисс на 90 градусов чтобы они не перекрывали друг друга
$graph->xaxis->SetLabelAngle(90);

//Установим шрифт для заголовка графика
$graph->title->SetFont(FF_VERDANA,FS_NORMAL,12);
//Установим заголовок графика
$graph->title->Set($str);
//Установим шрифт дла заголовка оси ординат
$graph->yaxis->title->SetFont(FF_ARIAL,FS_NORMAL,8);
//Установим заголовок оси ординат
$graph->yaxis->title->Set("Измерение (мВ)");
//Установим размеры полей будут располагаться заголовки
$graph->SetMargin(70,80,50,150);
//Установим расстояние между осью ординат и заголовком оси ординат
$graph->yaxis->SetTitlemargin(50);
//Установим цвет фона области рисунка, где расположены линии графика
$graph->SetColor('cadetblue1');
//Установим цвет фона полей рисунка, где располагаются заголовки
$graph->SetMarginColor('lightblue3');
//
Добавим эффект тени от всего изображения.
$graph->SetShadow();
//Установим место расположение легенды на рисунке
$graph->legend->Pos(0.01, 0.4, 'right', 'center');
//Выводим график
$graph->Stroke();
}

//Сохраним в переменных значение данных полученных в результате GET запроса
$IDmodem=$_GET['ID'];
$day_begin=$_GET['day_begin'];
$month_begin=$_GET['month_begin'];
$year_begin=$_GET['year_begin'];
$day_end=$_GET['day_end'];
$month_end=$_GET['month_end'];
$year_end=$_GET['year_end'];

//По GET запросу мы получили числа соответствующие дате, месяцу и году. Для преобразования полученных значений в UNIX - время используем функцию mktime
$timeUnixBegin=mktime(0, 0, 0, $month_begin, $day_begin, $year_begin)-1000000000;
//echo $timeUnixBegin."<br>";
$timeUnixEnd=mktime(23, 59, 59, $month_end, $day_end, $year_end)-1000000000;
//echo $timeUnixEnd."<br>";

//Из базы данных посредством SQL запроса извлекаем данные полей AI0AI1 и Time удовлетворяющие условию при котором значение поля Time входит в запрошенный временной промежуток. Кстати, если бы в базе данных время хранилось в формате DateTime, что конечно было бы удобней человеку, то в MySQL есть функция UNIX_TIMESTAMP() преобразующая время из формата DateTime в UNIX. SQL запрос выглядел бы так:
"SELECT * FROM aa WHERE Id='$IDmodem' and UNIX_TIMESTAMP(Time)>'$timeUnixBegin' and UNIX_TIMESTAMP(Time)<'$timeUnixEnd'"
$db=mysql_connect("localhost", "alex", "12345");
mysql_select_db("tc65t",$db);
mysql_query("set names cp1251");
$result=mysql_query("SELECT * FROM tc65tdbnew WHERE id='$IDmodem' and Time>'$timeUnixBegin' and Time<'$timeUnixEnd'",$db);

//Из данных полученных в результате SQL запроса создадим массивы со значениями времени в формате UNIX и со значениями аналоговых сигналов со входов AI0 и AI1 модема.  
$dayDB=array();
$AI0DB=array();
$AI1DB=array();
$myrow=mysql_fetch_array($result);
do{
array_push($dayDB,$myrow['Time']);
//echo $myrow['Time']." ";
array_push($AI0DB,$myrow['AI0']);
//echo $myrow['AI0']." ";
array_push($AI1DB,$myrow['AI1']);
//echo $myrow['AI1']."<br>";
}while($myrow=mysql_fetch_array($result));

//На основе массива со значением времени в формате UNIX создадим массив со значением времени в формате DateTime.
$day_time=array();
for($i=0; $i<count($dayDB); $i++)
{
$date = date_create();
date_timestamp_set($date, $dayDB[$i]+1000000000);
array_push($day_time,date_format($date, 'Y-m-d H:i:s'));
}
//Выводим график, вызвав рассмотренную ранее функцию.
graphDB($AI0DB, $AI1DB, $day_time, $IDmodem);

?>
 



Архив рассмотренных php- скриптов,  реализующих веб интерфейс: WebWatchTC65.rar

 

 

 


 

 







 

 

 


 

 

 

 

 

 

 
 

 

 

Hosted by uCoz