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

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