Сервер домашньої метеостанції на Arduino - віджет для OS X

З'явився у мене комп'ютер Apple. Не сказати, щоб я про нього сильно мріяв, але вдалося купити б/у за прийнятну ціну, і я вирішився. Полмісяця пролежав він мертвим вантажем, і з'явилося час зайнятися ним. Після тижня спілкування розумієш, чому комп'ютери Apple вважають найкращими. Зовсім інший рівень спілкування.

Після перших захоплень, бажання щось запрограмувати. Робимо віджет для OS X для сервера домашньої метеостанції на Arduino

Віджети представляють собою невеликі несамостійні програми з простим графічним інтерфейсом. У більшості випадків вони використовуються для швидкого отримання необхідної інформації з Інтернету і служать своєрідною альтернативою браузеру. 

В операційній системі Mac OS X Lion передбачена зручна середа розробника, що дозволяє дещо полегшити цей процес. Ця програма отримала назву Dashcode. Завантажити програму Dashcode можна безкоштовно зі сторінки https://developer.apple.com/downloads/index.action,

для цього необхідно зареєструватися на сайті developer.apple.com.

Встановлюємо програму. У мене встановлена остання версія OS X - 10.9 Mavericks. При запуску програми Dashcode вона видає помилку:

Дана версія програми не може бути використана з даною версією OS X. Пропонують відкотитися до версії OS X 10.8. Виявляється, Apple не розробила додаток Dashcode для даної версії операційної системи ?!!! Пропонують почекати. ???? - уявляв раніше Apple компанією, де все до дрібниць.

Пробуємо запустити Dashcode в терміналі. Відкриваємо Finder -- Програми -- xcode44dashcode6938116a.dmg.

Для додатку Dashcode.app вибираємо Показати вміст пакета.

Через деякий час додаток з'являється в панелі Dock, але вікно не відкривається. Натискаємо на значок Dashcode і вікно програми відкрите. 

Тепер можна розпочати програмування віджета.

Створюємо порожній проект, при цьому можна вибрати кілька стандартних шаблонів, але вибираємо Custom - користувацький.

Базовий віджет має основний і допоміжний стани (відповідно, front і back у лівій панелі). Перше відображається в звичайному режимі роботи, друге — для налаштування параметрів віджета. Переключатися між ними можна вибираючи відповідні пункти в списку компонентів зліва. 

Відкриваємо бібліотеку компонентів — (кнопка   Library справа вгорі) і перетаскуємо на віджет потрібні компоненти, тут мені достатньо компонентів типу Text для front і один компонент типу TextField для back. Тепер відкриваємо   Inspector (також кнопка справа вгорі) і з його допомогою налаштовуємо розміри, кольори і так далі для нашого віджета.

GUI нашого віджета готовий. Тепер можна запустити віджет на виконання і по натисканню кнопок i і Done виробляти переключення між панелями front і back.

Далі програмна реалізація віджета. Код пишеться на мові JavaScript. Правимо файл main.js.

Необхідно по таймеру раз у 2 хвилини звертатися за адресою 77.39.66.172:10001.

function startTimer(msec)
{
    updateTimer = setTimeout("updateStats()", msec);
}

function stopTimer()
{
    clearTimeout(updateTimer);
}

function updateStats()
{
    alert("Це працює!");
    execStatsRequest();
    startTimer(updateInterval);
} 

При цьому будемо отримувати дані в форматі JSON. Після парсинга даних виводимо їх у відповідні поля віджета.

function execStatsRequest()
{
        var Url = "http://"+ip_address;
        alert("Url= " + Url);

        xmlHttp = new XMLHttpRequest(); 
        xmlHttp.onreadystatechange = processStatsRequest;
        xmlHttp.overrideMimeType('application/json');
        xmlHttp.open("GET", Url, true);
        xmlHttp.send();
}

function processStatsRequest() 
{
     if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
    {
      alert(xmlHttp.responseText);
      try  
        {
        var data = JSON.parse(xmlHttp.responseText);
        document.getElementById("valT1").innerText =data.meteo.temp1;
        document.getElementById("valT2").innerText =data.meteo.temp3;
        document.getElementById("valH").innerText =data.meteo.humidity4;
        document.getElementById("valP").innerText =data.meteo.pressure5;
        var datenow=new Date();
        var strdatetime=(datenow.getHours()<10) ? ("0"+datenow.getHours().toString()) :(datenow.getHours().toString());
        strdatetime+=":";
        strdatetime+=(datenow.getMinutes()<10) ? ("0"+datenow.getMinutes().toString()) :(datenow.getMinutes().toString());
        strdatetime+=":";
        strdatetime+=(datenow.getSeconds()<10) ? ("0"+datenow.getSeconds().toString()) :(datenow.getSeconds().toString());
        strdatetime+=" ";
        strdatetime+=(datenow.getDate()<10) ? ("0"+datenow.getDate().toString()) :(datenow.getDate().toString());
        strdatetime+="-";
        strdatetime+=(datenow.getMonth()<9) ? ("0"+(datenow.getMonth()+1).toString()) :((datenow.getMonth()+1).toString());
        strdatetime+="-";
        strdatetime+=""+(datenow.getYear()+1900).toString()+"";
        document.getElementById("timeDay").innerText=strdatetime;               
        }
      catch(e)
        {
        alert("помилка");
        }
    }
 }

Також виводимо час останнього успішного отримання даних

Зворотна сторона віджета - зміна ip-адреси блоку датчиків. При виході з зворотного боку (натискаючи кнопку Готово) зберігаємо нове значення ip-адреси і робимо новий запит на отримання даних датчиків. Таймер на час видимості зворотного боку зупиняється.

function showBack(event)
{
    var front = document.getElementById("front");
    var back = document.getElementById("back");

    if (window.widget) {
        widget.prepareForTransition("ToBack");
    }

    front.style.display = "none";
    back.style.display = "block";

    if (window.widget) {
        setTimeout('widget.performTransition();', 0);
    }
    //
    stopTimer();    
    alert("showBack!");
}
function showFront(event)
{
    var front = document.getElementById("front");
    var back = document.getElementById("back");

    if (window.widget) {
        widget.prepareForTransition("ToFront");
    }

    front.style.display="block";
    back.style.display="none";
   if (window.widget) {
        setTimeout('widget.performTransition();', 0);
    }
    //
    ip_address=document.getElementById("ipSensors").value;
    savePrefs();    
    //loadPrefs();    
    execStatsRequest();
    startTimer(updateInterval);
}

Також необхідно написати процедури збереження параметра (ip-адреси)  

function loadPrefs()
{
    var ip = widget.preferenceForKey("weatheripsensors");
    ip_address=ip;
    document.getElementById("ipSensors").value=ip;
}

function savePrefs()
{   alert("зберегти=");
    widget.setPreferenceForKey(document.getElementById("ipSensors").value, "weatheripsensors");    
}

 

Зберігати налаштування необхідно постійно, щоб показувати останні значення видане сервером метео, він часто зависає. Тепер у мене показання з домашніх датчиків не тільки на планшеті, але і на екрані Mac'а, який у мене завжди з собою на роботі.

І відео установки і роботи віджета (на відео варіант з 20 сек запитом даних)

В прикріплених файлах сам віджет і файли проекту

Прикреплені файли:
Top