Это продолжение статьи, в которой рассмотрен USB HID термометр USB термометр на ATmega8
Компьютерная программа была доработана и теперь, показания термометра можно узнать, находясь в любой точке земного шара, с помощью любого браузера.
Вот код программы
; Для компиляции программы, нужна библиотека HID_Lib http://pure-basic.narod.ru/libs.html#HID_Lib #USB_PID=$EF04 #USB_VID=$AAAA #NO_Device="Нет связи с термометром" LoadFont(2,"Arial",22,#PB_Font_Bold) CurrentThermo.f=0 #ProgName="Web-сервер - USB градусник" Port=80 ; На этом порту будет работать сервер *Buffer = AllocateMemory(10000) If InitNetwork() = 0 MessageRequester(#ProgName, "Ошибка инициализации сетевой библиотеки!", #MB_OK|#MB_ICONERROR) End EndIf Procedure FindDevice_Timer() ; Периодическая (каждые 400 мс.) проверка доступности термометра Shared DeviceHandle Static Old_Test Test=HID_Lib_DeviceTest(#USB_PID, #USB_VID) ; Есть ли требуемое USB HID устройство? If Test<>Old_Test Old_Test=Test If Test HID_Lib_CloseDevice(DeviceHandle) DeviceHandle=HID_Lib_OpenDevice(#USB_PID, #USB_VID) ; Подключение к USB HID устройству SetGadgetText(0,"Термометр подключён") Else HID_Lib_CloseDevice(DeviceHandle) ; Разрыв связи с USB HID устройством DeviceHandle=0 SetGadgetText(0,#NO_Device) SetGadgetText(1,"OFF") SysTrayIconToolTip(1,"OFF") EndIf EndIf EndProcedure Procedure Thread(*x) ; Эта процедура работает в отдельном потоке Shared DeviceHandle Shared CurrentThermo.f Dim In.a(4) ; Байтовый массив, используемый как бцфер приёма данных. Repeat If DeviceHandle ; Установлена ли связь с USB термометром? In(0)=0 If HID_Lib_ReadDevice(DeviceHandle, @In(), 3) = 3 ; Чтение данных из USB термометра Temp.w=In(2) Temp<<8 ; Сдвиг влево на 8 позиций Temp | In(1) Result.f=Temp/16 CurrentThermo=Result SetGadgetText(1,StrF(Result,1)+" °C") ; Отображение температуры в окне SysTrayIconToolTip(1,StrF(Result,1)+" °C") ; Отображение температуры в трее EndIf Else Delay(10) EndIf ForEver EndProcedure Procedure.s Generate_HTML_Code() ; Динамическая генерация HTML кода. Shared DeviceHandle Shared CurrentThermo.f Protected HTML_Code.s If DeviceHandle StatusSensor.s="<span style="+Chr(34)+"color: RGB(51, 0, 153);"+Chr(34)+"> Подключён</span><br>" Else StatusSensor.s="<span style="+Chr(34)+"color: RGB(255, 0, 0);"+Chr(34)+"> Не обнаружен</span><br>" EndIf HTML_Code="" HTML_Code+"<html><head><title>"+#ProgName+"</title>" HTML_Code+"<STYLE TYPE="+Chr(34)+"text/css"+Chr(34)+"><!—BODY {background-color: black; font-family: Verdana; color: white; font-size: 9px} —> </STYLE>" HTML_Code+"<meta http-equiv="+Chr(34)+"Content-Type"+Chr(34)+" content="+Chr(34)+"text/html; Charset=windows-1251"+Chr(34) HTML_Code+"<META HTTP-EQUIV="+Chr(34)+"Refresh"+Chr(34)+" CONTENT="+Chr(34)+"2;URL="+Chr(34)+">" HTML_Code+"</head><body><b>USB термометр</b>"+StatusSensor If DeviceHandle HTML_Code+"</br><b>Текущая температура - <span style="+Chr(34)+"font-weight: bold>; color: rgb(0, 102, 0);"+Chr(34)+">"+StrF(CurrentThermo,1)+" °C </span></b><br>" EndIf HTML_Code+"</body></html>" ProcedureReturn HTML_Code EndProcedure Procedure Server_Event(*xx) ; Отдельный поток, в котором обрабатываются Web-сервером запросы от браузеров. Shared *Buffer Repeat SEvent = NetworkServerEvent() If SEvent ClientID = EventClient() Select SEvent Case #PB_NetworkEvent_Connect ; Новый клиент подключился к серверу Case #PB_NetworkEvent_Data ; От клинета пришли данные OutHTML.s=Generate_HTML_Code() Len_HTML=Len(OutHTML) ReceiveNetworkData(ClientID, *Buffer, 10000) SendNetworkString(ClientID, "HTTP/1.0 200 OK"+Chr($0D)+Chr($0A)) SendNetworkString(ClientID, "Server: "+#ProgName+Chr($0D)+Chr($0A)) SendNetworkString(ClientID, "Content-Length: "+Str(Len_HTML)+Chr($0D)+Chr($0A)) SendNetworkString(ClientID, "Content-Type: text/html"+Chr($0D)+Chr($0A)) SendNetworkString(ClientID, Chr($0D)+Chr($0A)) SendNetworkString(ClientID, OutHTML) Case #PB_NetworkEvent_File ; От клиента пришел файл Case #PB_NetworkEvent_Disconnect ; Клиент разорвал соединение с сервером EndSelect Else Delay(20) EndIf ForEver EndProcedure If CreatePopupMenu(0) ; Контекстное меню для трея MenuItem(1,"Показать окно") MenuItem(2,"Скрыть окно") MenuBar() MenuItem(3,"Выход") EndIf If CreateNetworkServer(2, Port , #PB_Network_TCP) ; Открываем окно OpenWindow(0,0,0,200,70,"Web Server USB t°", #PB_Window_MinimizeGadget|#PB_Window_Invisible|#PB_Window_ScreenCentered) StickyWindow(0,1) TextGadget(0,24,4,162,16,#NO_Device,#PB_Text_Center) StringGadget(1,36,24,140,40,"OFF",#PB_Text_Center|#PB_String_ReadOnly) SetGadgetFont(1,FontID(2)) SetGadgetColor(1,#PB_Gadget_FrontColor,$DF0000) FindDevice_Timer() ;HideWindow(0,0) AddWindowTimer(0,1,400) ; Запуск таймера CreateThread(@Thread(),0) ; Создание отдельного потока из процедуры Thread() CreateThread(@Server_Event(),0) AddSysTrayIcon(1,WindowID(0),ExtractIcon_(0,ProgramFilename(),0)) ; Иконка в трее SysTrayIconToolTip(1,"OFF") Repeat ; Главный цикл проги Repeat - Until Event=WaitWindowEvent() ; Идентификатор события If Event=#PB_Event_Timer If EventTimer()=1 FindDevice_Timer() ; Вызов процедуры по таймеру, каждые 400 мс. EndIf ElseIf Event=#PB_Event_SysTray ; Собтыие в трее Select EventType() Case #PB_EventType_RightClick ; Клик правой кнопокй мышки DisplayPopupMenu(0,WindowID(0)) ; Отображение контекстного меню Case #PB_EventType_LeftClick ; Клик левой кнопкой мышки HideWindow(0,0) ; Отображение окна SetWindowState(0,#PB_Window_Normal) SetActiveWindow(0) EndSelect ElseIf Event=#PB_Event_MinimizeWindow ; Окно свернули HideWindow(0,1) ; Скрываем главное окно ElseIf Event=#PB_Event_Menu ; Событие в меню Select EventMenu() Case 1 ; Пункт "Показать окно" HideWindow(0,0) SetWindowState(0,#PB_Window_Normal) SetActiveWindow(0) Case 2 ; Пункт "Скрыть окно" HideWindow(0,1) Case 3 ; Пункт "Выход" Break EndSelect EndIf Until Event=#PB_Event_CloseWindow ; Прерывание главного цикла при закрытии окна Else MessageRequester(#ProgName, "Не удалось создать сервер на "+Str(Port)+" порту!", #MB_OK|#MB_ICONERROR) EndIf End
После запуска программы, её значок появится в трее
Если щелкнуть правой кнопкой мышки по значку и появившемся меню, выбрать пункт Показать окно
то на экране появится оно программы, в котором отобразится текущая, температура, полученная из ранее рассмотренного устройства - USB термометра
В программе организован Web-сервер, который собственно и позволяет работать с браузером.
Если программа запущена на одном компьютере с браузером, то в адресной строке браузера, следует ввести адрес http://127.0.0.1
Если же связь производится через интернет, что в адресной строке, нужно ввести IP адрес компьютера, на котором запущена рассматриваемая программа.
В браузере отобразится примерно такой текст:
В программе предусмотрено автообновление Веб-странички, каждые 2 секунды, но к сожалению у меня оно работает только в браузере Mozilla Firefox.
Я с HTML плохо дружу, поэтому сделал очень примитивную динамически генерируемую Web-страничку.
При необходимости, её внешний вид можно значительно улучшить, а так же добавить возможность управления программой, прямо из браузера.