source: asp3_tinet_ecnl_arm/trunk/app4_aircon/src/echonet_main.c@ 352

Last change on this file since 352 was 352, checked in by coas-nagasima, 6 years ago

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 28.0 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37
38/*
39 * サンプルプログラム(1)の本体
40 */
41
42#include <kernel.h>
43#include <t_syslog.h>
44#include <t_stdlib.h>
45#include <sil.h>
46#include <string.h>
47#include "syssvc/serial.h"
48#include "syssvc/syslog.h"
49#include "kernel_cfg.h"
50#include "echonet_main.h"
51#include "echonet_cfg.h"
52#include "target_kernel_impl.h"
53#include "gpio_api.h"
54#include "analogin_api.h"
55#include "adafruit_st7735.h"
56#include "draw_font.h"
57
58/* TODO: メーカーコードを設定 */
59#define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */
60
61/* ノードプロファイルオブジェクト */
62struct ecn_cls0EF0_t node_profile_data = {
63 0x30, /* 動作状態 */
64 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
65 {
66 0xFE, /* 下位通信層IDフィールド */
67 { MAKER_CODE }, /* メーカーコード */
68 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
69 },
70 0x0000, /* 異常内容 */
71 { MAKER_CODE }, /* メーカーコード */
72};
73
74/* 家庭用エアコンクラス */
75struct ecn_cls0130_t home_air_conditioner_data = {
76 0x30, /* 動作状態 */
77 0x41, /* 運転モード設定 */
78 0x14, /* 温度設定値 */
79 0x00, /* 設置場所 */
80 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
81 0x42, /* 異常発生状態 */
82 { MAKER_CODE }, /* メーカーコード */
83};
84
85/* ノードプロファイルオブジェクト */
86struct ecn_cls0EF0_t temp_sensor_01_node_data = {
87 0x30, /* 動作状態 */
88 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
89 {
90 0xFE, /* 下位通信層IDフィールド */
91 { MAKER_CODE }, /* メーカーコード */
92 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
93 },
94 0x0000, /* 異常内容 */
95 { MAKER_CODE }, /* メーカーコード */
96};
97
98/* 温度センサクラス */
99struct ecn_cls0011_t temp_sensor_01_data = {
100 0x31, /* 動作状態 */
101 0xF554, /* 温度計測値 */
102 0x00, /* 設置場所 */
103 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
104 0x42, /* 異常発生状態 */
105 { MAKER_CODE }, /* メーカーコード */
106};
107
108/* ノードプロファイルオブジェクト */
109struct ecn_cls0EF0_t temp_sensor_02_node_data = {
110 0x30, /* 動作状態 */
111 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
112 {
113 0xFE, /* 下位通信層IDフィールド */
114 { MAKER_CODE }, /* メーカーコード */
115 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
116 },
117 0x0000, /* 異常内容 */
118 { MAKER_CODE }, /* メーカーコード */
119};
120
121/* 温度センサクラス */
122struct ecn_cls0011_t temp_sensor_02_data = {
123 0x31, /* 動作状態 */
124 0xF554, /* 温度計測値 */
125 0x00, /* 設置場所 */
126 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
127 0x42, /* 異常発生状態 */
128 { MAKER_CODE }, /* メーカーコード */
129};
130
131/* ノードプロファイルオブジェクト */
132struct ecn_cls0EF0_t temp_sensor_03_node_data = {
133 0x30, /* 動作状態 */
134 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
135 {
136 0xFE, /* 下位通信層IDフィールド */
137 { MAKER_CODE }, /* メーカーコード */
138 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
139 },
140 0x0000, /* 異常内容 */
141 { MAKER_CODE }, /* メーカーコード */
142};
143
144/* 温度センサクラス */
145struct ecn_cls0011_t temp_sensor_03_data = {
146 0x31, /* 動作状態 */
147 0xF554, /* 温度計測値 */
148 0x00, /* 設置場所 */
149 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
150 0x42, /* 異常発生状態 */
151 { MAKER_CODE }, /* メーカーコード */
152};
153
154/* ノードプロファイルオブジェクト */
155struct ecn_cls0EF0_t temp_sensor_04_node_data = {
156 0x30, /* 動作状態 */
157 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
158 {
159 0xFE, /* 下位通信層IDフィールド */
160 { MAKER_CODE }, /* メーカーコード */
161 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
162 },
163 0x0000, /* 異常内容 */
164 { MAKER_CODE }, /* メーカーコード */
165};
166
167/* 温度センサクラス */
168struct ecn_cls0011_t temp_sensor_04_data = {
169 0x31, /* 動作状態 */
170 0xF554, /* 温度計測値 */
171 0x00, /* 設置場所 */
172 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
173 0x42, /* 異常発生状態 */
174 { MAKER_CODE }, /* メーカーコード */
175};
176
177/*
178 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
179 */
180int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
181{
182 ER ret;
183 uint8_t data[1];
184
185 /* サイズが1以外は受け付けない */
186 if(size != 1)
187 return 0;
188
189 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
190
191 switch(*(uint8_t *)src){
192 /* ONの場合 */
193 case 0x30:
194 /* OFFの場合 */
195 case 0x31:
196 *((uint8_t *)item->exinf) = *((uint8_t *)src);
197 /* メインタスクに通知 */
198 data[0] = 0x80;
199 ret = ecn_brk_wai(data, sizeof(data));
200 if(ret != E_OK){
201 syslog(LOG_ERROR, "ecn_brk_wai");
202 return 2;
203 }
204 break;
205 /* 0x30か0x31以外は受け付けない */
206 default:
207 return 0;
208 }
209
210 return 1;
211}
212
213/*
214 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
215 */
216int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
217{
218 /* サイズが1以外は受け付けない */
219 if(size != 1)
220 return 0;
221
222 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
223
224 switch(*(uint8_t *)src){
225 /* 異常発生ありの場合 */
226 case 0x41:
227 /* 異常発生なしの場合 */
228 case 0x42:
229 *((uint8_t *)item->exinf) = *((uint8_t *)src);
230 break;
231 /* 0x41か0x42以外は受け付けない */
232 default:
233 return 0;
234 }
235
236 return 1;
237}
238
239/*
240 * 運転モード設定設定関数
241 */
242int ecn_cls0130_propertyB0_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
243{
244 ER ret;
245 uint8_t data[1];
246
247 /* サイズが1以外は受け付けない */
248 if(size != 1)
249 return 0;
250
251 switch(*(uint8_t *)src){
252 /* 自動の場合 */
253 case 0x41:
254 /* 冷房の場合 */
255 case 0x42:
256 /* 暖房の場合 */
257 case 0x43:
258 /* 除湿の場合 */
259 case 0x44:
260 /* 送風の場合 */
261 case 0x45:
262 /* その他の場合 */
263 case 0x40:
264 *((uint8_t *)item->exinf) = *((uint8_t *)src);
265 /* メインタスクに通知 */
266 data[0] = 0xB0;
267 ret = ecn_brk_wai(data, sizeof(data));
268 if(ret != E_OK){
269 syslog(LOG_ERROR, "ecn_brk_wai");
270 return 2;
271 }
272 break;
273 default:
274 /* 上記以外は受け付けない */
275 return 0;
276 }
277
278 return 1;
279}
280
281/*
282 * 温度設定値設定関数
283 */
284int ecn_cls0130_propertyB3_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
285{
286 ER ret;
287 uint8_t data[1];
288
289 /* サイズが1以外は受け付けない */
290 if(size != 1)
291 return 0;
292
293 /* 0℃~50℃ */
294 if((*(uint8_t *)src >= 0x00) && (*(uint8_t *)src <= 0x32)){
295 *((uint8_t *)item->exinf) = *((uint8_t *)src);
296 /* メインタスクに通知 */
297 data[0] = 0xB3;
298 ret = ecn_brk_wai(data, sizeof(data));
299 if(ret != E_OK){
300 syslog(LOG_ERROR, "ecn_brk_wai");
301 return 2;
302 }
303 }
304 /* 上記以外は受け付けない */
305 else{
306 return 0;
307 }
308
309 return 1;
310}
311
312static void main_initialize();
313static int main_get_timer();
314static void main_progress(int interval);
315static void main_recv_esv(T_EDATA *esv);
316static void main_break_wait(uint8_t *brkdat, int32_t len);
317static void main_timeout();
318
319/*
320 * メインタスク
321 */
322void echonet_main_task(intptr_t exinf)
323{
324 ER ret, ret2;
325 SYSTIM prev, now;
326 int timer;
327 T_EDATA *esv;
328 uint8_t brkdat[64];
329 int32_t len;
330
331 /* アプリケーションの初期化 */
332 main_initialize();
333
334 ret2 = get_tim(&now);
335 if (ret2 != E_OK){
336 syslog(LOG_ERROR, "get_tim");
337 return;
338 }
339
340 for(;;){
341 prev = now;
342
343 /* タイマー取得 */
344 timer = main_get_timer();
345
346 /* 応答電文待ち */
347 ret = ecn_trcv_esv(&esv, timer);
348 if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)){
349 syslog(LOG_ERROR, "ecn_trcv_esv");
350 break;
351 }
352
353 ret2 = get_tim(&now);
354 if (ret2 != E_OK){
355 syslog(LOG_ERROR, "get_tim");
356 break;
357 }
358
359 /* 時間経過 */
360 main_progress(now - prev);
361
362 /* Echonet電文受信の場合 */
363 if (ret == E_OK) {
364 /* Echonet電文受信処理 */
365 main_recv_esv(esv);
366
367 /* 領域解放 */
368 ret = ecn_rel_esv(esv);
369 if (ret != E_OK){
370 syslog(LOG_ERROR, "ecn_rel_esv");
371 break;
372 }
373 }
374 /* 応答電文待ちの割り込みの場合 */
375 else if (ret == E_BRK) {
376 /* 応答電文待ちの割り込みデータ取得 */
377 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
378 if (ret != E_OK){
379 syslog(LOG_ERROR, "ecn_get_brk_dat");
380 break;
381 }
382
383 /* 応答電文待ちの割り込み処理 */
384 main_break_wait(brkdat, len);
385
386 /* 領域解放 */
387 ret = ecn_rel_esv(esv);
388 if (ret != E_OK){
389 syslog(LOG_ERROR, "ecn_rel_esv");
390 break;
391 }
392 }
393
394 /* タイムアウト処理 */
395 main_timeout();
396 }
397}
398
399bool_t started = false;
400
401void echonet_change_netif_link(uint8_t link_up, uint8_t up)
402{
403 ER ret;
404
405 if (link_up == 0)
406 return;
407
408 if (up && !started) {
409 started = true;
410
411 /* ECHONETミドルウェアを起動 */
412 ret = ecn_sta_svc();
413 if (ret != E_OK)
414 return;
415
416 /* ECHONETミドルウェアを起動するのを待つ */
417 dly_tsk(100);
418 }
419
420 /* メインタスクに通知 */
421 uint8_t data[2];
422 data[0] = 0x01;
423 data[1] = up ? 0x01 : 0x02;
424 ret = ecn_brk_wai(data, sizeof(data));
425 if (ret != E_OK) {
426 syslog(LOG_ERROR, "ecn_brk_wai");
427 return;
428 }
429}
430
431enum main_state_t{
432 main_state_idle,
433 main_state_search,
434 main_state_survey_01,
435 main_state_survey_02,
436 main_state_survey_03,
437 main_state_survey_04,
438 main_state_interval,
439};
440
441int main_timer = TMO_FEVR;
442enum main_state_t main_state = main_state_idle;
443int16_t main_ave_templ;
444bool_t main_tmp_fan_on;
445bool_t main_ctl_fan_on;
446gpio_t relay_sw;
447
448int main_btn_timer = TMO_FEVR;
449
450int main_lcd_timer = TMO_FEVR;
451int main_lcd_state = 0;
452
453/* ジョイスティック種別 */
454#define BUTTON_NONE 0
455#define BUTTON_DOWN 1
456#define BUTTON_LEFT 2
457#define BUTTON_SELECT 3
458#define BUTTON_UP 4
459#define BUTTON_RIGHT 5
460
461analogin_t joystick;
462static uint8_t main_read_button(analogin_t *obj);
463
464bool_t main_btn1_state;
465int main_btn1_count = 0;
466bool_t main_btn2_state;
467int main_btn2_count = 0;
468
469LCD_Handler_t lcd;
470LCD_DrawProp_t drawProp;
471
472enum main_rly_state_t{
473 main_rly_state_off,
474 main_rly_state_on
475};
476
477int main_rly_timer = TMO_FEVR;
478enum main_rly_state_t main_rly_state = main_rly_state_off;
479static void main_rly_onoff(bool_t onoff);
480
481/*
482 * 初期化
483 */
484static void main_initialize()
485{
486 uint8_t btn;
487
488 /* 1秒後に温度センサーを探す */
489 main_timer = 1000 * 1000;
490
491 gpio_init_out(&relay_sw, P4_4);
492
493 /* ジョイスティックの初期化 */
494 analogin_init(&joystick, P1_12);
495
496 /* 10ms後にボタン状態を確認 */
497 main_btn_timer = 10 * 1000;
498
499 /* ボタン状態読み込み */
500 btn = main_read_button(&joystick);
501 main_btn1_state = btn == BUTTON_LEFT;
502 main_btn2_state = btn == BUTTON_RIGHT;
503
504 // 1.8" TFTの初期化
505 spi_init(&lcd.hspi, P10_14, P10_15, P10_12, NC);
506 spi_format(&lcd.hspi, 8, 0, 0);
507 spi_frequency(&lcd.hspi, 1000000);
508
509 gpio_init_out(&lcd.cs_pin, P10_13);
510 gpio_init_out(&lcd.rs_pin, P8_15);
511 gpio_init_out(&lcd.rst_pin, P8_14);
512 gpio_init_out(&lcd.cs2_pin, NC);
513
514 lcd_initR(&lcd, /*INITR_REDTAB?*/INITR_18BLACKTAB);
515
516 drawProp.hlcd = &lcd;
517 drawProp.TextColor = ST7735_BLACK;
518 drawProp.BackColor = ST7735_WHITE;
519 drawProp.pFont = NULL;
520 lcd_fillScreen(&drawProp);
521
522 /* 1秒後にLCD表示を更新 */
523 main_lcd_state = 10;
524 main_lcd_timer = 1000 * 1000;
525
526 ER ret = act_tsk(MAIN_TASK);
527 if (ret != E_OK) {
528 syslog(LOG_ERROR, "act_tsk");
529 }
530}
531
532/*
533 * タイマー取得
534 */
535static int main_get_timer()
536{
537 int result = main_timer;
538
539 if((result == TMO_FEVR)
540 || ((main_btn_timer != TMO_FEVR) && (main_btn_timer < result))){
541 result = main_btn_timer;
542 }
543
544 if((result == TMO_FEVR)
545 || ((main_lcd_timer != TMO_FEVR) && (main_lcd_timer < result))){
546 result = main_lcd_timer;
547 }
548
549 if((result == TMO_FEVR)
550 || ((main_rly_timer != TMO_FEVR) && (main_rly_timer < result))){
551 result = main_rly_timer;
552 }
553
554 return result;
555}
556
557/*
558 * 時間経過
559 */
560static void main_progress(int interval)
561{
562 if(main_timer != TMO_FEVR){
563 main_timer -= interval;
564 if(main_timer < 0){
565 main_timer = 0;
566 }
567 }
568
569 if(main_btn_timer != TMO_FEVR){
570 main_btn_timer -= interval;
571 if(main_btn_timer < 0){
572 main_btn_timer = 0;
573 }
574 }
575
576 if(main_lcd_timer != TMO_FEVR){
577 main_lcd_timer -= interval;
578 if(main_lcd_timer < 0){
579 main_lcd_timer = 0;
580 }
581 }
582
583 if(main_rly_timer != TMO_FEVR){
584 main_rly_timer -= interval;
585 if(main_rly_timer < 0){
586 main_rly_timer = 0;
587 }
588 }
589}
590
591static void main_survey_templ(int no);
592static void main_calc_ave_templ();
593
594/*
595 * Echonet電文受信処理
596 */
597static void main_recv_esv(T_EDATA *esv)
598{
599 ER ret;
600 ID eobjid;
601 uint8_t epc;
602 uint8_t pdc;
603 uint8_t p_edt[256];
604 T_ENUM_EPC enm;
605
606 eobjid = ecn_get_eobj(esv);
607 if(eobjid == EOBJ_NULL){
608 syslog(LOG_ERROR, "ecn_get_eobj");
609 }
610
611 ret = ecn_itr_ini(&enm, esv);
612 if(ret != E_OK){
613 syslog(LOG_ERROR, "ecn_itr_ini");
614 return;
615 }
616
617 for(;;) {
618 while((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
619 switch (epc) {
620 case 0xD6:
621 switch(main_state){
622 case main_state_idle:
623 case main_state_search:
624 /* 温度センサー1温度監視 */
625 main_survey_templ(1);
626 main_state = main_state_survey_01;
627 main_timer = 1000 * 1000;
628 break;
629 }
630 break;
631 case 0xE0:
632 switch(main_state){
633 case main_state_survey_01:
634 /* 温度センサー2温度監視 */
635 main_survey_templ(2);
636 main_state = main_state_survey_02;
637 main_timer = 1000 * 1000;
638 break;
639 case main_state_survey_02:
640 /* 温度センサー3温度監視 */
641 main_survey_templ(3);
642 main_state = main_state_survey_03;
643 main_timer = 1000 * 1000;
644 break;
645 case main_state_survey_03:
646 /* 温度センサー4温度監視 */
647 main_survey_templ(4);
648 main_state = main_state_survey_04;
649 main_timer = 1000 * 1000;
650 break;
651 case main_state_survey_04:
652 /* 温度センサー1~4平均値計算 */
653 main_calc_ave_templ();
654 /* 温度監視休止10秒 */
655 main_state = main_state_interval;
656 main_timer = 10000 * 1000;
657 break;
658 }
659 break;
660 }
661 }
662 if(ret != E_BOVR){
663 syslog(LOG_ERROR, "ecn_itr_nxt");
664 break;
665 }
666 if(enm.is_eof)
667 break;
668 }
669}
670
671/*
672 * 温度センサー温度監視
673 */
674static void main_survey_templ(int no)
675{
676 const ID senserids[] = {
677 TEMP_SENSOR_01_EOBJ,
678 TEMP_SENSOR_02_EOBJ,
679 TEMP_SENSOR_03_EOBJ,
680 TEMP_SENSOR_04_EOBJ
681 };
682 ER ret;
683 T_EDATA *esv;
684
685 /* 温度センサー動作状態取得電文作成 */
686 ret = ecn_esv_get(&esv, senserids[no - 1], 0x80);
687 if(ret != E_OK){
688 syslog(LOG_ERROR, "ecn_esv_get");
689 return;
690 }
691
692 /* 温度計測値取得追加 */
693 ret = ecn_add_epc(esv, 0xE0);
694 if(ret != E_OK){
695 syslog(LOG_ERROR, "ecn_add_epc");
696
697 ret = ecn_rel_esv(esv);
698 if(ret != E_OK){
699 syslog(LOG_ERROR, "ecn_rel_esv");
700 }
701 return;
702 }
703
704 /* 電文送信 */
705 ret = ecn_snd_esv(esv);
706 if(ret != E_OK){
707 syslog(LOG_ERROR, "ecn_snd_esv");
708 }
709}
710
711/*
712 * 温度センサー1~4平均値計算
713 */
714static void main_calc_ave_templ()
715{
716 int count = 0;
717 int templ = 0;
718
719 if(temp_sensor_01_data.property80 == 0x30){
720 templ += ((((uint16_t)temp_sensor_01_data.propertyE0) & 0xFF) << 8)
721 | ((((uint16_t)temp_sensor_01_data.propertyE0) & 0xFF00) >> 8);
722 count++;
723 }
724 if(temp_sensor_02_data.property80 == 0x30){
725 templ += ((((uint16_t)temp_sensor_02_data.propertyE0) & 0xFF) << 8)
726 | ((((uint16_t)temp_sensor_02_data.propertyE0) & 0xFF00) >> 8);
727 count++;
728 }
729 if(temp_sensor_03_data.property80 == 0x30){
730 templ += ((((uint16_t)temp_sensor_03_data.propertyE0) & 0xFF) << 8)
731 | ((((uint16_t)temp_sensor_03_data.propertyE0) & 0xFF00) >> 8);
732 count++;
733 }
734 if(temp_sensor_04_data.property80 == 0x30){
735 templ += ((((uint16_t)temp_sensor_04_data.propertyE0) & 0xFF) << 8)
736 | ((((uint16_t)temp_sensor_04_data.propertyE0) & 0xFF00) >> 8);
737 count++;
738 }
739
740 if(count > 0){
741 templ = templ / count;
742 if(templ < -2732)
743 main_ave_templ = 0x8000;
744 else if(templ > 32766)
745 main_ave_templ = 0x7FFF;
746 else
747 main_ave_templ = (int16_t)templ;
748
749 /* FANが停止中の場合 */
750 if(!main_tmp_fan_on){
751 if(main_ave_templ > (10 * home_air_conditioner_data.propertyB3 + 5)){
752 main_tmp_fan_on = true;
753
754 /* リレー出力をON */
755 if (!main_ctl_fan_on)
756 main_rly_onoff(true);
757 }
758 }
759 /* FANが稼働中の場合 */
760 else{
761 if(main_ave_templ < (10 * home_air_conditioner_data.propertyB3 - 5)){
762 main_tmp_fan_on = false;
763
764 /* リレー出力をOFF */
765 if (!main_ctl_fan_on)
766 main_rly_onoff(false);
767 }
768 }
769 }
770 else
771 main_ave_templ = 0x7FFF;
772}
773
774/*
775 * 応答電文待ちの割り込み処理
776 */
777static void main_break_wait(uint8_t *brkdat, int32_t len)
778{
779 switch (brkdat[0]) {
780 case 0x01:
781 // Link up/down
782 break;
783 }
784
785 /* 運転モードが送風の場合、温度によらずFANをON */
786 if (*brkdat == 0xB0) {
787 bool_t prev = main_ctl_fan_on;
788 main_ctl_fan_on = home_air_conditioner_data.propertyB0 == 0x45;
789
790 if (prev != main_ctl_fan_on) {
791 if (main_ctl_fan_on) {
792 /* リレー出力をON */
793 if (!main_tmp_fan_on)
794 main_rly_onoff(true);
795 }
796 else {
797 /* リレー出力をOFF */
798 if (!main_tmp_fan_on)
799 main_rly_onoff(false);
800 }
801 }
802 }
803}
804
805static void main_ontimer();
806static void main_btn_ontimer();
807static void main_lcd_ontimer();
808static void main_rly_ontimer();
809
810/*
811 * タイムアウト処理
812 */
813static void main_timeout()
814{
815 if(main_timer == 0){
816 main_ontimer();
817 }
818
819 if(main_btn_timer == 0){
820 main_btn_ontimer();
821 }
822
823 if(main_lcd_timer == 0){
824 main_lcd_ontimer();
825 }
826
827 if(main_rly_timer == 0){
828 main_rly_ontimer();
829 }
830}
831
832static void main_search();
833
834static void main_ontimer()
835{
836 switch(main_state){
837 case main_state_idle:
838 case main_state_search:
839 /* 温度センサー再検索 */
840 main_search();
841 main_state = main_state_search;
842 main_timer = 5000 * 1000;
843 break;
844 case main_state_survey_01:
845 /* 応答がない場合動作状態OFFとする */
846 temp_sensor_01_data.property80 = 0x31;
847 /* 温度センサー2温度監視 */
848 main_survey_templ(2);
849 main_state = main_state_survey_02;
850 main_timer = 1000 * 1000;
851 break;
852 case main_state_survey_02:
853 /* 応答がない場合動作状態OFFとする */
854 temp_sensor_02_data.property80 = 0x31;
855 /* 温度センサー3温度監視 */
856 main_survey_templ(3);
857 main_state = main_state_survey_03;
858 main_timer = 1000 * 1000;
859 break;
860 case main_state_survey_03:
861 /* 応答がない場合動作状態OFFとする */
862 temp_sensor_03_data.property80 = 0x31;
863 /* 温度センサー4温度監視 */
864 main_survey_templ(4);
865 main_state = main_state_survey_04;
866 main_timer = 1000 * 1000;
867 break;
868 case main_state_survey_04:
869 /* 応答がない場合動作状態OFFとする */
870 temp_sensor_04_data.property80 = 0x31;
871 /* 温度センサー1~4平均値計算 */
872 main_calc_ave_templ();
873 /* 温度監視休止10秒 */
874 main_state = main_state_interval;
875 main_timer = 10000 * 1000;
876 break;
877 case main_state_interval:
878 /* 温度センサー1温度監視 */
879 main_survey_templ(1);
880 main_state = main_state_survey_01;
881 main_timer = 1000 * 1000;
882 break;
883 }
884}
885
886static void main_search()
887{
888 ER ret;
889 T_EDATA *esv;
890
891 /* 温度センサー検索 */
892 ret = ecn_esv_inf_req(&esv, EOBJ_NULL, 0xD6);
893 if(ret != E_OK){
894 syslog(LOG_ERROR, "ecn_esv_inf_req");
895 return;
896 }
897
898 /* 電文送信 */
899 ret = ecn_snd_esv(esv);
900 if(ret != E_OK){
901 syslog(LOG_ERROR, "ecn_snd_esv");
902 }
903}
904
905static void main_btn1_change(bool_t push);
906static void main_btn2_change(bool_t push);
907
908static void main_btn_ontimer()
909{
910 uint8_t btn;
911
912 /* 10ms後にボタン状態を確認 */
913 main_btn_timer = 10 * 1000;
914
915 /* ボタン状態読み込み */
916 btn = main_read_button(&joystick);
917
918 /* ボタン1の処理 */
919 if ((btn == BUTTON_LEFT) && !main_btn1_state) {
920 main_btn1_count++;
921 if(main_btn1_count > 10){
922 main_btn1_count = 0;
923 main_btn1_state = true;
924
925 main_btn1_change(true);
926 }
927 }
928 else if ((btn != BUTTON_LEFT) && main_btn1_state) {
929 main_btn1_count++;
930 if(main_btn1_count > 10){
931 main_btn1_count = 0;
932 main_btn1_state = false;
933
934 main_btn1_change(false);
935 }
936 }
937
938 /* ボタン2の処理 */
939 if ((btn == BUTTON_RIGHT) && !main_btn2_state) {
940 main_btn2_count++;
941 if(main_btn2_count > 10){
942 main_btn2_count = 0;
943 main_btn2_state = true;
944
945 main_btn2_change(true);
946 }
947 }
948 else if ((btn != BUTTON_RIGHT) && main_btn2_state) {
949 main_btn2_count++;
950 if(main_btn2_count > 10){
951 main_btn2_count = 0;
952 main_btn2_state = false;
953
954 main_btn2_change(false);
955 }
956 }
957}
958
959static void main_lcd_ontimer()
960{
961 char power[] = "電源:off";
962 char temp1[] = "設定温度:+00℃";
963 char temp2[] = "測定温度:+00.0℃";
964 char mode[] = "運転モード:自動 ";
965 char *mode_texts[] = { "自動 ", "冷房 ", "暖房 ", "除湿 ", "送風 ", "その他" };
966 char *btn_texts[] = { "none ", "down ", "left ", "select", "up ", "right " };
967 int temp, btn;
968
969 switch (main_lcd_state) {
970 case 0:
971 if (home_air_conditioner_data.property80 == 0x30) {
972 power[9] = 'o';
973 power[10] = 'n';
974 power[11] = ' ';
975 }
976 else {
977 power[9] = 'o';
978 power[10] = 'f';
979 power[11] = 'f';
980 }
981 lcd_drawString(&lcd, &power[9], X_LINE_HALF_TO_PIX(&lcd, 6) + 10, Y_ROW_TO_PIX(&lcd, main_lcd_state + 4) + 10, ST7735_BLACK, ST7735_WHITE);
982 main_lcd_state++;
983 break;
984 case 1:
985 temp1[15] = (home_air_conditioner_data.propertyB3 >= 0) ? ' ' : '-';
986 temp = (home_air_conditioner_data.propertyB3 / 10) % 10;
987 if (temp < 0)
988 temp = -temp;
989 temp1[16] = '0' + temp;
990 temp = (home_air_conditioner_data.propertyB3 / 1) % 10;
991 if (temp < 0)
992 temp = -temp;
993 temp1[17] = '0' + temp;
994 lcd_drawString(&lcd, &temp1[15], X_LINE_HALF_TO_PIX(&lcd, 10) + 10, Y_ROW_TO_PIX(&lcd, main_lcd_state + 4) + 10, ST7735_BLACK, ST7735_WHITE);
995 main_lcd_state++;
996 break;
997 case 2:
998 temp2[15] = (main_ave_templ >= 0) ? ' ' : '-';
999 temp = (main_ave_templ / 100) % 10;
1000 if (temp < 0)
1001 temp = -temp;
1002 temp2[16] = '0' + temp;
1003 temp = (main_ave_templ / 10) % 10;
1004 if (temp < 0)
1005 temp = -temp;
1006 temp2[17] = '0' + temp;
1007 temp = (main_ave_templ / 1) % 10;
1008 if (temp < 0)
1009 temp = -temp;
1010 temp2[19] = '0' + temp;
1011 lcd_drawString(&lcd, &temp2[15], X_LINE_HALF_TO_PIX(&lcd, 10) + 10, Y_ROW_TO_PIX(&lcd, main_lcd_state + 4) + 10, ST7735_BLACK, ST7735_WHITE);
1012 main_lcd_state++;
1013 break;
1014 case 3:
1015 temp = home_air_conditioner_data.propertyB0 - 0x40;
1016 lcd_drawString(&lcd, mode_texts[temp], X_LINE_HALF_TO_PIX(&lcd, 12) + 10, Y_ROW_TO_PIX(&lcd, main_lcd_state + 4) + 10, ST7735_BLACK, ST7735_WHITE);
1017 main_lcd_state++;
1018 break;
1019 case 4:
1020 case 5:
1021 main_lcd_state++;
1022 break;
1023 case 6:
1024 btn = main_read_button(&joystick);
1025 lcd_drawString(&lcd, btn_texts[btn], X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, 10) + 10, ST7735_BLACK, ST7735_WHITE);
1026 main_lcd_state++;
1027 break;
1028 case 9:
1029 main_lcd_state = 0;
1030 break;
1031 case 10:
1032 lcd_drawString(&lcd, "エアコン", X_LINE_TO_PIX(&lcd, 9) + 10, Y_ROW_TO_PIX(&lcd, 0) + 10, ST7735_BLACK, ST7735_WHITE);
1033 lcd_drawString(&lcd, power, X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, 0 + 4) + 10, ST7735_BLACK, ST7735_WHITE);
1034 lcd_drawString(&lcd, temp1, X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, 1 + 4) + 10, ST7735_BLACK, ST7735_WHITE);
1035 lcd_drawString(&lcd, temp2, X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, 2 + 4) + 10, ST7735_BLACK, ST7735_WHITE);
1036 lcd_drawString(&lcd, mode, X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, 3 + 4) + 10, ST7735_BLACK, ST7735_WHITE);
1037 main_lcd_state = 0;
1038 break;
1039 default:
1040 main_lcd_state++;
1041 break;
1042 }
1043
1044 /* 100ms後にLCD表示を更新 */
1045 main_lcd_timer = 100 * 1000;
1046}
1047
1048static uint8_t main_read_button(analogin_t *obj)
1049{
1050 float a = analogin_read(obj);
1051
1052 a *= 5.0;
1053
1054 //printf("Button read analog = %f\r\n",a);
1055 if (a < 0.2)
1056 return BUTTON_DOWN;
1057 if (a < 1.0)
1058 return BUTTON_RIGHT;
1059 if (a < 1.7)
1060 return BUTTON_SELECT;
1061 if (a < 2.6)
1062 return BUTTON_UP;
1063 if (a < 4.6)
1064 return BUTTON_LEFT;
1065 else
1066 return BUTTON_NONE;
1067}
1068
1069uint8_t main_templ = 20; /* 20℃ */
1070
1071/*
1072 * ボタン1状態変化処理
1073 */
1074static void main_btn1_change(bool_t push)
1075{
1076 ER ret;
1077 T_EDATA *esv;
1078 uint8_t p_edt[1];
1079
1080 /* 押されて戻った時に処理する */
1081 if(push)
1082 return;
1083
1084 /* 設定温度 */
1085 if(main_templ > 0)
1086 main_templ--; /* - 1℃ */
1087
1088 p_edt[0] = main_templ;
1089
1090 /* プロパティ設定電文作成 */
1091 ret = ecn_esv_seti(&esv, HOME_AIR_CONDITIONER_EOBJ, 0xB3, 1, p_edt);
1092 if(ret != E_OK){
1093 syslog(LOG_ERROR, "ecn_esv_seti");
1094 return;
1095 }
1096
1097 /* 電文送信 */
1098 ecn_snd_esv(esv);
1099 if(ret != E_OK){
1100 syslog(LOG_ERROR, "ecn_snd_esv");
1101 }
1102}
1103
1104/*
1105 * ボタン2状態変化処理
1106 */
1107static void main_btn2_change(bool_t push)
1108{
1109 ER ret;
1110 T_EDATA *esv;
1111 uint8_t p_edt[1];
1112
1113 /* 押されて戻った時に処理する */
1114 if(push)
1115 return;
1116
1117 /* 設定温度 */
1118 if(main_templ < 50)
1119 main_templ++; /* + 1.0℃ */
1120
1121 p_edt[0] = main_templ;
1122
1123 /* プロパティ設定電文作成 */
1124 ret = ecn_esv_seti(&esv, HOME_AIR_CONDITIONER_EOBJ, 0xB3, 1, p_edt);
1125 if(ret != E_OK){
1126 syslog(LOG_ERROR, "ecn_esv_seti");
1127 return;
1128 }
1129
1130 /* 電文送信 */
1131 ecn_snd_esv(esv);
1132 if(ret != E_OK){
1133 syslog(LOG_ERROR, "ecn_snd_esv");
1134 }
1135}
1136#if 1
1137static void main_rly_onoff(bool_t onoff)
1138{
1139 if(onoff){
1140 /* リレー出力をON */
1141 gpio_write(&relay_sw, 1);
1142 }
1143 else{
1144 /* リレー出力をOFF */
1145 gpio_write(&relay_sw, 0);
1146 }
1147}
1148
1149static void main_rly_ontimer()
1150{
1151 main_rly_timer = TMO_FEVR;
1152}
1153#else
1154static void main_rly_onoff(bool_t onoff)
1155{
1156 /* リレー出力をON */
1157 gpio_write(&relay_sw, 1);
1158
1159 /* 500msパルス出力 */
1160 main_rly_state = main_rly_state_on;
1161 main_rly_timer = 500;
1162}
1163
1164/*
1165 * リレーパルス出力処理
1166 */
1167static void main_rly_ontimer()
1168{
1169 switch(main_rly_state)
1170 {
1171 case main_rly_state_off:
1172 main_rly_timer = TMO_FEVR;
1173 break;
1174 case main_rly_state_on:
1175 /* リレー出力をOFF */
1176 gpio_write(&relay_sw, 0);
1177
1178 main_rly_state = main_rly_state_off;
1179 main_rly_timer = TMO_FEVR;
1180 break;
1181 }
1182}
1183#endif
Note: See TracBrowser for help on using the repository browser.