source: asp3_tinet_ecnl_rx/trunk/app7_buzzer/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: 14.2 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
54/* TODO: メーカーコードを設定 */
55#define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */
56
57/* ノードプロファイルオブジェクト */
58struct ecn_cls0EF0_t node_local_profile_data = {
59 0x30, /* 動作状態 */
60 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
61 {
62 0xFE, /* 下位通信層IDフィールド */
63 { MAKER_CODE }, /* メーカーコード */
64 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
65 },
66 { MAKER_CODE }, /* メーカーコード */
67};
68
69/* 電気ポットクラス */
70struct ecn_cls03B2_t electric_hot_water_pot_data = {
71 0x30, /* 動作状態 */
72 0x41, /* 湯切れ警告状態 */
73 0x41, /* 出湯状態 */
74 0x00, /* 設置場所 */
75 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
76 0x42, /* 異常発生状態 */
77 { MAKER_CODE }, /* メーカーコード */
78};
79
80/* ノードプロファイルオブジェクト */
81struct ecn_cls0EF0_t node_remote_profile_data = {
82 0x30, /* 動作状態 */
83 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
84 {
85 0xFE, /* 下位通信層IDフィールド */
86 { MAKER_CODE }, /* メーカーコード */
87 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
88 },
89 { MAKER_CODE }, /* メーカーコード */
90};
91
92/* ブザークラス */
93struct ecn_cls02A0_t buzzer_data = {
94 0x30, /* 動作状態 */
95 0x41, /* 音発生設定 */
96 0x00, /* 設置場所 */
97 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
98 0x42, /* 異常発生状態 */
99 { MAKER_CODE }, /* メーカーコード */
100};
101
102/*
103 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
104 */
105int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
106{
107 /* サイズが1以外は受け付けない */
108 if (size != 1)
109 return 0;
110
111 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
112
113 switch (*(uint8_t *)src) {
114 /* ONの場合 */
115 case 0x30:
116 *((uint8_t *)item->exinf) = *((uint8_t *)src);
117 /* LEDの"."をON */
118 sil_wrb_mem((uint8_t *)0x0008C02A, sil_reb_mem((uint8_t *)0x0008C02A) | 0x40);
119 break;
120 /* OFFの場合 */
121 case 0x31:
122 *((uint8_t *)item->exinf) = *((uint8_t *)src);
123 /* LEDの"."をOFF */
124 sil_wrb_mem((uint8_t *)0x0008C02A, sil_reb_mem((uint8_t *)0x0008C02A) & ~0x40);
125 break;
126 /* 0x30か0x31以外は受け付けない */
127 default:
128 return 0;
129 }
130
131 return 1;
132}
133
134/*
135 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
136 */
137int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
138{
139 /* サイズが1以外は受け付けない */
140 if (size != 1)
141 return 0;
142
143 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
144
145 switch (*(uint8_t *)src) {
146 /* 異常発生ありの場合 */
147 case 0x41:
148 /* 異常発生なしの場合 */
149 case 0x42:
150 *((uint8_t *)item->exinf) = *((uint8_t *)src);
151 break;
152 /* 0x41か0x42以外は受け付けない */
153 default:
154 return 0;
155 }
156
157 return 1;
158}
159
160/*
161 * 音発生設定設定関数
162 */
163int ecn_cls02A0_propertyB1_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
164{
165 uint8_t sseg = sil_reb_mem((uint8_t *)0x0008C02A) & ~0x07;
166
167 /* サイズが1以外は受け付けない */
168 if (size != 1)
169 return 0;
170
171 switch (*(uint8_t *)src) {
172 /* 音発生有の場合 */
173 case 0x41:
174 *((uint8_t *)item->exinf) = *((uint8_t *)src);
175 /* LEDを"001"と表示 */
176 sil_wrb_mem((uint8_t *)0x0008C02A, sseg | 0x20);
177 break;
178 /* 音発生無の場合 */
179 case 0x42:
180 *((uint8_t *)item->exinf) = *((uint8_t *)src);
181 /* LEDを"010"と表示 */
182 sil_wrb_mem((uint8_t *)0x0008C02A, sseg | 0x40);
183 break;
184 default:
185 /* 上記以外は受け付けない */
186 return 0;
187 }
188
189 return 1;
190}
191
192/*
193 * 湯切れ警告状態設定関数
194 */
195int no_water_warning_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
196{
197 ER ret;
198 uint8_t data[2];
199
200 /* サイズが1以外は受け付けない */
201 if (size != 1)
202 return 0;
203
204 *((uint8_t *)item->exinf) = *((uint8_t *)src);
205
206 /* メインタスクに通知 */
207 data[0] = 0x01;
208 data[1] = (*((uint8_t *)src) == 0x41) ? 0x01 : 0x00;
209 ret = ecn_brk_wai(data, sizeof(data));
210 if (ret != E_OK) {
211 syslog(LOG_ERROR, "ecn_brk_wai");
212 }
213
214 return 1;
215}
216
217/*
218 * 出湯状態設定関数
219 */
220int discharge_status_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
221{
222 ER ret;
223 uint8_t data[2];
224
225 /* サイズが1以外は受け付けない */
226 if (size != 1)
227 return 0;
228
229 *((uint8_t *)item->exinf) = *((uint8_t *)src);
230
231 /* メインタスクに通知 */
232 data[0] = 0x02;
233 data[1] = (*((uint8_t *)src) == 0x41) ? 0x01 : 0x00;
234 ret = ecn_brk_wai(data, sizeof(data));
235 if (ret != E_OK) {
236 syslog(LOG_ERROR, "ecn_brk_wai");
237 }
238
239 return 1;
240}
241
242static void main_initialize();
243static int main_get_timer();
244static void main_progress(int interval);
245static void main_recv_esv(T_EDATA *esv);
246static void main_break_wait(uint8_t *brkdat, int32_t len);
247static void main_timeout();
248
249/*
250 * メインタスク
251 */
252void echonet_main_task(intptr_t exinf)
253{
254 ER ret, ret2;
255 SYSTIM prev, now;
256 int timer;
257 T_EDATA *esv;
258 uint8_t brkdat[64];
259 int32_t len;
260
261 /* アプリケーションの初期化 */
262 main_initialize();
263
264 ret2 = get_tim(&now);
265 if (ret2 != E_OK) {
266 syslog(LOG_ERROR, "get_tim");
267 return;
268 }
269
270 for (;;) {
271 prev = now;
272
273 /* タイマー取得 */
274 timer = main_get_timer();
275
276 /* 応答電文待ち */
277 ret = ecn_trcv_esv(&esv, timer);
278 if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)) {
279 syslog(LOG_ERROR, "ecn_trcv_esv");
280 break;
281 }
282
283 ret2 = get_tim(&now);
284 if (ret2 != E_OK) {
285 syslog(LOG_ERROR, "get_tim");
286 break;
287 }
288
289 /* 時間経過 */
290 main_progress(now - prev);
291
292 /* Echonet電文受信の場合 */
293 if (ret == E_OK) {
294 /* Echonet電文受信処理 */
295 main_recv_esv(esv);
296
297 /* 領域解放 */
298 ret = ecn_rel_esv(esv);
299 if (ret != E_OK) {
300 syslog(LOG_ERROR, "ecn_rel_esv");
301 break;
302 }
303 }
304 /* 応答電文待ちの割り込みの場合 */
305 else if (ret == E_BRK) {
306 /* 応答電文待ちの割り込みデータ取得 */
307 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
308 if (ret != E_OK) {
309 syslog(LOG_ERROR, "ecn_get_brk_dat");
310 break;
311 }
312
313 /* 応答電文待ちの割り込み処理 */
314 main_break_wait(brkdat, len);
315
316 /* 領域解放 */
317 ret = ecn_rel_esv(esv);
318 if (ret != E_OK) {
319 syslog(LOG_ERROR, "ecn_rel_esv");
320 break;
321 }
322 }
323
324 /* タイムアウト処理 */
325 main_timeout();
326 }
327}
328
329void echonet_change_netif_link(uint8_t link_up, uint8_t up)
330{
331 ER ret;
332
333 if (link_up == 0)
334 return;
335
336 if (up) {
337 /* インスタンスリスト通知の送信 */
338 ret = ecn_ntf_inl();
339 if (ret != E_OK) {
340 syslog(LOG_ERROR, "ecn_ntf_inl");
341 }
342 }
343
344 /* メインタスクに通知 */
345 uint8_t data[2];
346 data[0] = 0x01;
347 ret = ecn_brk_wai(data, sizeof(data));
348 if (ret != E_OK) {
349 syslog(LOG_ERROR, "ecn_brk_wai");
350 return;
351 }
352}
353
354enum main_state_t {
355 main_state_start,
356 main_state_idle,
357 main_state_search,
358 main_state_buzzer_on,
359};
360
361int main_timer = TMO_FEVR;
362enum main_state_t main_state = main_state_start;
363
364int main_nop_timer = TMO_FEVR;
365
366/*
367 * 初期化
368 */
369static void main_initialize()
370{
371 /* LEDを"000"と表示 */
372 sil_wrb_mem((uint8_t *)0x0008C02A, 0x00);
373
374 /* ECHONETミドルウェアを起動するのを待つ */
375 main_state = main_state_start;
376 main_timer = 1000 * 1000;
377
378 /* メインタスクを起動 */
379 ER ret = act_tsk(MAIN_TASK);
380 if (ret != E_OK) {
381 syslog(LOG_ERROR, "act_tsk");
382 }
383}
384
385/*
386 * タイマー取得
387 */
388static int main_get_timer()
389{
390 int result = main_timer;
391
392 if ((result == TMO_FEVR)
393 || ((main_nop_timer != TMO_FEVR) && (main_nop_timer < result))) {
394 result = main_nop_timer;
395 }
396
397 return result;
398}
399
400/*
401 * 時間経過
402 */
403static void main_progress(int interval)
404{
405 if (main_timer != TMO_FEVR) {
406 main_timer -= interval;
407 if (main_timer < 0) {
408 main_timer = 0;
409 }
410 }
411
412 if (main_nop_timer != TMO_FEVR) {
413 main_nop_timer -= interval;
414 if (main_nop_timer < 0) {
415 main_nop_timer = 0;
416 }
417 }
418}
419
420/*
421 * Echonet電文受信処理
422 */
423static void main_recv_esv(T_EDATA *esv)
424{
425 ER ret;
426 ID eobjid;
427 uint8_t epc;
428 uint8_t pdc;
429 uint8_t p_edt[256];
430 T_ENUM_EPC enm;
431
432 eobjid = ecn_get_eobj(esv);
433 if (eobjid == EOBJ_NULL) {
434 syslog(LOG_ERROR, "ecn_get_eobj");
435 return;
436 }
437
438 ret = ecn_itr_ini(&enm, esv);
439 if (ret != E_OK) {
440 syslog(LOG_ERROR, "ecn_itr_ini");
441 return;
442 }
443
444 for (;;) {
445 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
446 switch (epc) {
447 case 0xD6:
448 switch (main_state) {
449 case main_state_search:
450 if (eobjid == POT_NODE_EOBJ) {
451 /* 電気ポット検索完了 */
452 main_state = main_state_idle;
453 main_timer = TMO_FEVR;
454 }
455 break;
456 }
457 break;
458 }
459 }
460 if (ret != E_BOVR) {
461 syslog(LOG_ERROR, "ecn_itr_nxt");
462 break;
463 }
464 if (enm.is_eof)
465 break;
466 }
467}
468
469static void main_buzzer_on()
470{
471 ER ret;
472 T_EDATA *esv;
473 uint8_t p_edt[1];
474
475 switch (main_state) {
476 case main_state_idle:
477 p_edt[0] = 0x41; /* 音発生有 */
478
479 /* プロパティ設定電文作成 */
480 ret = ecn_esv_seti(&esv, BUZZER_EOBJ, 0xB1, 1, p_edt);
481 if (ret != E_OK) {
482 syslog(LOG_ERROR, "ecn_esv_seti");
483 break;
484 }
485
486 /* 電文送信 */
487 ecn_snd_esv(esv);
488 if (ret != E_OK) {
489 syslog(LOG_ERROR, "ecn_snd_esv");
490 break;
491 }
492
493 main_state = main_state_buzzer_on;
494 main_timer = 1000 * 1000; /* 1秒鳴動 */
495 break;
496 case main_state_buzzer_on:
497 main_timer = 1000 * 1000; /* 1秒延長 */
498 break;
499 }
500}
501
502static void main_buzzer_off()
503{
504 ER ret;
505 T_EDATA *esv;
506 uint8_t p_edt[1];
507
508 switch (main_state) {
509 case main_state_buzzer_on:
510 p_edt[0] = 0x42; /* 音発生無 */
511
512 /* プロパティ設定電文作成 */
513 ret = ecn_esv_seti(&esv, BUZZER_EOBJ, 0xB1, 1, p_edt);
514 if (ret != E_OK) {
515 syslog(LOG_ERROR, "ecn_esv_seti");
516 break;
517 }
518
519 /* 電文送信 */
520 ecn_snd_esv(esv);
521 if (ret != E_OK) {
522 syslog(LOG_ERROR, "ecn_snd_esv");
523 break;
524 }
525
526 main_state = main_state_idle;
527 main_timer = TMO_FEVR;
528 break;
529 }
530}
531
532/*
533 * 応答電文待ちの割り込み処理
534 */
535static void main_break_wait(uint8_t *brkdat, int32_t len)
536{
537 if (brkdat[0] == 0x01) {
538 // Link up/down
539 return;
540 }
541
542 if (len < 2)
543 return;
544
545 switch (brkdat[0]) {
546 case 0x01:
547 if (brkdat[1] != 0)
548 main_buzzer_on();
549 else
550 main_buzzer_off();
551 break;
552 case 0x02:
553 if (brkdat[1] == 0)
554 main_nop_timer = 5000 * 1000; /* 5秒後にブザーON */
555 break;
556 }
557}
558
559static void main_ontimer();
560static void main_nop_timeout();
561
562/*
563 * タイムアウト処理
564 */
565static void main_timeout()
566{
567 if (main_timer == 0) {
568 main_ontimer();
569 }
570
571 if (main_nop_timer == 0) {
572 main_nop_timeout();
573 }
574}
575
576static void main_search();
577
578static void main_ontimer()
579{
580 ER ret;
581
582 switch (main_state) {
583 case main_state_start:
584 /* ECHONETミドルウェアを起動 */
585 ret = ecn_sta_svc();
586 if (ret != E_OK) {
587 syslog(LOG_ERROR, "ecn_sta_svc");
588 }
589
590 /* 1秒後にブザーを検索 */
591 main_state = main_state_search;
592 main_timer = 1000 * 1000;
593 break;
594 case main_state_search:
595 /* 電気ポット再検索 */
596 main_search();
597 main_state = main_state_search;
598 main_timer = 5000 * 1000;
599 break;
600 case main_state_buzzer_on:
601 main_buzzer_off();
602 break;
603 default:
604 main_state = main_state_idle;
605 main_timer = TMO_FEVR;
606 break;
607 }
608}
609
610static void main_search()
611{
612 ER ret;
613 T_EDATA *esv;
614
615 /* 電気ポット検索 */
616 ret = ecn_esv_inf_req(&esv, EOBJ_NULL, 0xD6);
617 if (ret != E_OK) {
618 syslog(LOG_ERROR, "ecn_esv_inf_req");
619 return;
620 }
621
622 /* 電文送信 */
623 ret = ecn_snd_esv(esv);
624 if (ret != E_OK) {
625 syslog(LOG_ERROR, "ecn_snd_esv");
626 }
627}
628
629static void main_nop_timeout()
630{
631 main_buzzer_on();
632
633 main_nop_timer = TMO_FEVR;
634}
Note: See TracBrowser for help on using the repository browser.