source: asp3_tinet_ecnl_rx/trunk/app4_aircon/src/echonet_main.c

Last change on this file was 400, checked in by coas-nagasima, 5 years ago

ファイルヘッダーの更新

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