source: EcnlProtoTool/trunk/mrbgems/mruby-ecnl/src/echonet_agent.c@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 31.1 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2015-2016 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者
7は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再é…
10å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
11 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13 * スコード中に含まれていること.
14 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15 * 用できる形で再é…
16å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
17å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
18 * 者
19マニュアルなど)に,上記の著作権表示,この利用条件および下記
20 * の無保証規定を掲載すること.
21 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22 * 用できない形で再é…
23å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
24 * と.
25 * (a) 再é…
26å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
27マニュアルなど)に,上記の著
28 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
29 * (b) 再é…
30å¸ƒã®å½¢æ…
31‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
32 * 報告すること.
33 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
34 * 害からも,上記著作権者
35およびTOPPERSプロジェクトをå…
36è²¬ã™ã‚‹ã“と.
37 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
38 * 由に基づく請求からも,上記著作権者
39およびTOPPERSプロジェクトを
40 * å…
41è²¬ã™ã‚‹ã“と.
42 *
43 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
44お
45 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
46 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
47 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
48 * の責任を負わない.
49 *
50 * @(#) $Id: echonet_agent.c 270 2017-02-09 04:03:47Z coas-nagasima $
51 */
52
53/*
54 * ECHONET Lite 動的生成ノード
55 */
56
57#include <mruby.h>
58#include <stdio.h>
59#include <stdlib.h>
60#include <stdarg.h>
61#include <string.h>
62#ifdef _MSC_VER
63#include <assert.h>
64#endif
65#include "echonet_task.h"
66#include "echonet_dbg.h"
67
68static ER ecn_agent_proc_get_device_list(ecnl_svc_task_t *svc, ecn_agent_t *agent, ECN_FBS_ID req);
69static ER ecn_agent_proc_get_device_info(ecnl_svc_task_t *svc, ecn_agent_t *agent, ECN_FBS_ID req);
70static void ecn_node_send_set_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
71static void ecn_node_send_get_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
72static void ecn_node_send_anno_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
73static void ecn_node_timeout_on_start(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
74static void ecn_node_next_proc_on_set_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj);
75static void ecn_node_timeout_on_set_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
76static void ecn_node_next_proc_on_get_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj);
77static void ecn_node_timeout_on_get_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
78static void ecn_node_next_proc_on_anno_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj);
79static void ecn_node_timeout_on_anno_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node);
80
81int ecn_agent_eprpset(ecnl_svc_task_t *svc, const EPRPINIB *item, const void *src, int size, bool_t *anno);
82int ecn_agent_eprpget(ecnl_svc_task_t *svc, const EPRPINIB *item, void *dst, int size);
83
84static ecn_agent_queue_t *cast_queue(ecn_obj_t *obj)
85{
86 return (ecn_agent_queue_t *)((intptr_t)obj - offsetof(ecn_agent_buffer_t, cnt.obj));
87}
88
89static ecn_obj_t *cast_obj(ecn_agent_queue_t *queue)
90{
91 return (ecn_obj_t *)((intptr_t)queue + offsetof(ecn_agent_buffer_t, cnt.obj));
92}
93
94static ecn_node_agent_t *cast_node(const EOBJCB *eobj)
95{
96 return (ecn_node_agent_t *)((intptr_t)eobj - offsetof(ecn_node_agent_t, node.eobj));
97}
98
99static ecn_obj_t *cast_obj2(const EOBJINIB *inib)
100{
101 return (ecn_obj_t *)((intptr_t)inib - offsetof(ecn_obj_t, inib));
102}
103
104static ecn_agent_t *cast_agent(const EPRPINIB *inib)
105{
106 return (ecn_agent_t *)((intptr_t)inib - offsetof(ecn_agent_t, eprpinib));
107}
108
109#define loc_cpu()
110#define unl_cpu()
111
112ER get_buf(ecn_agent_t *agent, ecn_agent_buffer_t **buf)
113{
114 ER ret = E_OK;
115
116 loc_cpu();
117
118 if (agent->blkpos < TNUM_AEOBJID) {
119 *buf = &agent->blockes[agent->blkpos++];
120 }
121 else if (agent->free == NULL) {
122 ret = E_TMOUT;
123 }
124 else{
125 *buf = agent->free;
126 agent->free = agent->free->hdr.free;
127 }
128
129 unl_cpu();
130
131 return ret;
132}
133
134ER rel_buf(ecn_agent_t *agent, ecn_agent_buffer_t *buf)
135{
136 if ((buf < &agent->blockes[0]) || (buf >= &agent->blockes[TNUM_AEOBJID]))
137 return E_PAR;
138
139 if ((((intptr_t)buf - (intptr_t)&agent->blockes[0]) % sizeof(ecn_agent_buffer_t)) != 0)
140 return E_PAR;
141
142 loc_cpu();
143
144 if (agent->free == NULL) {
145 agent->free = buf;
146 agent->free->hdr.free = NULL;
147 }
148 else {
149 ecn_agent_buffer_t *next = agent->free;
150 agent->free = buf;
151 agent->free->hdr.free = next;
152 }
153
154 unl_cpu();
155
156 return E_OK;
157}
158
159/*
160 * キューの初期化
161 *
162 * p_queueにはキューヘッダを指定する.
163 */
164static void
165ecn_agent_queue_init(ecn_agent_queue_t *p_queue)
166{
167#ifdef _DEBUG
168 p_queue->p_parent = p_queue;
169#endif
170 p_queue->p_prev = p_queue;
171 p_queue->p_next = p_queue;
172}
173
174/*
175 * キューの前エントリへの挿å…
176¥
177 *
178 * p_queueの前にp_entryを挿å…
179¥ã™ã‚‹ï¼Žp_queueにキューヘッダを指定した場
180 * 合には,キューの末尾にp_entryを挿å…
181¥ã™ã‚‹ã“とになる.
182 */
183static void
184ecn_agent_queue_add(ecn_agent_queue_t *p_queue, ecn_agent_queue_t *p_entry)
185{
186#ifdef _DEBUG
187 assert((p_queue->p_parent == p_queue) && (p_entry->p_parent == NULL));
188 p_entry->p_parent = p_queue;
189#endif
190 p_entry->p_prev = p_queue->p_prev;
191 p_entry->p_next = p_queue;
192 p_queue->p_prev->p_next = p_entry;
193 p_queue->p_prev = p_entry;
194}
195
196/*
197 * エントリの削除
198 *
199 * p_entryをキューから削除する.
200 */
201static void
202ecn_agent_queue_remove(ecn_agent_queue_t *p_queue, ecn_agent_queue_t *p_entry)
203{
204#ifdef _DEBUG
205 assert((p_queue->p_parent == p_queue) && (p_entry->p_parent == p_queue));
206 p_entry->p_parent = NULL;
207#endif
208 p_entry->p_prev->p_next = p_entry->p_next;
209 p_entry->p_next->p_prev = p_entry->p_prev;
210}
211
212ecn_node_t *ecn_agent_find_node(ecnl_svc_task_t *svc, ECN_ENOD_ID enodid)
213{
214 ecn_agent_t *agent = &svc->agent;
215 ecn_agent_queue_t *queue = agent->nodes.p_next;
216#ifdef _DEBUG
217 assert(queue->p_parent == &agent->nodes);
218#endif
219 for (; queue != &agent->nodes; queue = queue->p_next) {
220 ecn_node_t *node = (ecn_node_t *)cast_obj(queue);
221 if(node->enodId == enodid)
222 return node;
223 }
224
225 return NULL;
226}
227
228ecn_node_agent_t *ecn_agent_find_node2(ecnl_svc_task_t *svc, const EOBJCB *pk_eobj)
229{
230 ecn_agent_t *agent = &svc->agent;
231 ecn_agent_queue_t *queue;
232
233 if(pk_eobj == NULL)
234 return NULL;
235
236 queue = agent->nodes.p_next;
237#ifdef _DEBUG
238 assert(queue->p_parent == &agent->nodes);
239#endif
240 for (; queue != &agent->nodes; queue = queue->p_next) {
241 ecn_node_agent_t *node = (ecn_node_agent_t *)cast_obj(queue);
242 if(&node->node.eobj == pk_eobj)
243 return node;
244 }
245
246 return NULL;
247}
248
249ecn_obj_t *ecn_agent_find_eobj(const EOBJCB *pk_nod, T_ECN_EOJ eoj)
250{
251 ecn_agent_queue_t *devices = &cast_node(pk_nod)->node.devices;
252 ecn_agent_queue_t *queue = devices->p_next;
253#ifdef _DEBUG
254 assert(queue->p_parent == devices);
255#endif
256 for (; queue != devices; queue = queue->p_next) {
257 ecn_obj_t *obj = cast_obj(queue);
258 if (obj->inib.eojx1 != eoj.eojx1)
259 continue;
260 if (obj->inib.eojx2 != eoj.eojx2)
261 continue;
262 if (obj->inib.eojx3 != eoj.eojx3)
263 continue;
264
265 return obj;
266 }
267
268 return NULL;
269}
270
271ecn_obj_t *ecn_agent_find_obj2(ecn_node_agent_t *pk_nod, const EOBJINIB *pk_obj)
272{
273 ecn_agent_queue_t *devices = &pk_nod->node.devices;
274 ecn_agent_queue_t *queue = devices->p_next;
275#ifdef _DEBUG
276 assert(queue->p_parent == devices);
277#endif
278 for (; queue != devices; queue = queue->p_next) {
279 ecn_obj_t *obj = cast_obj(queue);
280 if (&obj->inib == pk_obj)
281 return obj;
282 }
283
284 return NULL;
285}
286
287ID ecn_agent_get_eobj(const EOBJINIB *pk_obj)
288{
289 return cast_obj2(pk_obj)->eobjId;
290}
291
292const EOBJINIB *ecn_agent_next_eobj(const EOBJCB *pk_nod, const EOBJINIB *pk_obj)
293{
294 ecn_agent_queue_t *devices = &cast_node(pk_nod)->node.devices;
295 ecn_obj_t *device = (ecn_obj_t *)pk_obj->exinf;
296 ecn_agent_queue_t *queue = cast_queue(device);
297#ifdef _DEBUG
298 assert(queue->p_parent == devices);
299#endif
300 if (queue == devices)
301 return NULL;
302
303 return &cast_obj(queue->p_next)->inib;
304}
305
306bool_t ecn_agent_get_eoj_enodid(ecnl_svc_task_t *svc, ID eobjid, T_ECN_EOJ *eoj, ECN_ENOD_ID *enodid)
307{
308 ecn_agent_t *agent = &svc->agent;
309 ecn_agent_buffer_t *buf;
310 int i = eobjid;
311
312 /* オブジェクトIDから実体を取得 */
313 i -= (svc->tmax_eobjid + 1);
314 if ((i < 0)
315 || (i >= (sizeof(agent->blockes) / sizeof(agent->blockes[0])))){
316 return false;
317 }
318
319 buf = &agent->blockes[i];
320 if(buf->cnt.obj.eobjId != eobjid)
321 return false;
322
323 /* オブジェクトのEOJをコピー */
324 memcpy(eoj, &buf->cnt.obj.inib.eojx1, sizeof(*eoj));
325
326 /* 所属するノードのオブジェクトIDを取得 */
327 if(buf->cnt.obj.inib.enodid == 0)
328 i = buf->cnt.obj.eobjId;
329 else
330 i = buf->cnt.obj.inib.enodid;
331
332 i -= (svc->tmax_eobjid + 1);
333 if ((i < 0)
334 || (i >= (sizeof(agent->blockes) / sizeof(agent->blockes[0])))){
335 return false;
336 }
337
338 /* ノードIDを取得 */
339 buf = &agent->blockes[i];
340 *enodid = buf->cnt.node.node.enodId;
341
342 return true;
343}
344
345void ecn_agent_set_epc_to_prop_map(uint8_t epc, uint8_t *propMap)
346{
347 int i, j;
348 if ((epc & 0x80) == 0)
349 return;
350 i = epc & 0xF;
351 j = (epc >> 4) - 8;
352 propMap[i] |= (1 << j);
353}
354
355bool_t ecn_agent_contains_epc_in_prop_map(uint8_t epc, uint8_t *propMap)
356{
357 int i, j;
358 if ((epc & 0x80) == 0)
359 return false;
360 i = epc & 0xF;
361 j = (epc >> 4) - 8;
362 return (propMap[i] & (1 << j)) != 0;
363}
364
365void ecn_agent_init(ecnl_svc_task_t *svc)
366{
367 svc->agent.eprpinib.eprpcd = 0x00; /* プロパティコード */
368 svc->agent.eprpinib.eprpatr = EPC_RULE_SET | EPC_RULE_GET; /* プロパティ属性 */
369 svc->agent.eprpinib.eprpsz = 255; /* プロパティのサイズ */
370 svc->agent.eprpinib.exinf = (intptr_t)&svc->agent; /* プロパティの拡張情
371å ± */
372 svc->agent.eprpinib.eprpset = ecn_agent_eprpset; /* プロパティの設定関数 */
373 svc->agent.eprpinib.eprpget = ecn_agent_eprpget; /* プロパティの取得関数 */
374
375 svc->agent.peprpinib = &svc->agent.eprpinib;
376
377 ecn_agent_queue_init(&svc->agent.nodes);
378}
379
380ecn_node_agent_t *ecn_agent_create_node(ecnl_svc_task_t *svc, ecn_agent_t *agent, T_EDATA *esv)
381{
382 mrb_state *mrb = svc->mrb;
383 ecn_agent_buffer_t *result = NULL;
384 ecn_node_agent_t *node;
385 uint8_t epc;
386 uint8_t pdc;
387 uint8_t edt[256];
388 T_ENUM_EPC enm;
389 ER ret;
390 T_ECN_EOJ *eoj, *end;
391
392 // プロパティ通知か取得応答で、
393 switch (esv->hdr.edata.esv) {
394 case ESV_GET_RES:
395 case ESV_GET_SNA:
396 case ESV_INF:
397 break;
398 default:
399 return NULL;
400 }
401
402 // ノードプロファイル宛の場合
403 eoj = &esv->hdr.edata.seoj;
404 if ((eoj->eojx1 != EOJ_X1_PROFILE) || (eoj->eojx2 != EOJ_X2_NODE_PROFILE)
405 || (eoj->eojx3 != 0x01))
406 return NULL;
407
408 ret = ecn_itr_ini(&enm, esv);
409 if(ret != E_OK){
410 ECN_DBG_PUT("ecn_itr_ini");
411 }
412
413 while (ecn_itr_nxt(mrb, &enm, &epc, &pdc, &edt) == E_OK) {
414 switch (epc) {
415 // インスタンスリスト通知の場合
416 case 0xD5:
417 // 自ノードインスタンスリストS通知の場合
418 case 0xD6:
419 // サイズが合わない場合
420 if (pdc != (1 + edt[0] * sizeof(T_ECN_EOJ)))
421 return NULL;
422
423 ret = get_buf(agent, &result);
424 if(ret != E_OK){
425 ECN_DBG_PUT("get_buf");
426 return NULL;
427 }
428
429 memset(result, 0, sizeof(*result));
430 node = &result->cnt.node;
431 node->node.enodId = ((T_ECN_FST_BLK *)esv)->hdr.sender.id;
432 node->node.base.svc = svc;
433 node->node.base.eobjId = svc->tmax_eobjid + 1 + (((intptr_t)result - (intptr_t)agent->blockes) / sizeof(agent->blockes[0]));
434 node->node.base.inib.enodid = 0;
435 node->node.base.inib.eobjatr = EOBJ_SYNC_REMOTE_NODE;
436 node->node.base.inib.exinf = (intptr_t)node;
437 node->node.base.inib.eojx1 = eoj->eojx1;
438 node->node.base.inib.eojx2 = eoj->eojx2;
439 node->node.base.inib.eojx3 = eoj->eojx3;
440 node->node.base.inib.eprp = &agent->peprpinib;
441 node->node.base.inib.eprpcnt = 0;
442 ecn_agent_set_epc_to_prop_map(0xD5, node->node.base.pmapGet);
443 ecn_agent_set_epc_to_prop_map(0xD6, node->node.base.pmapGet);
444 ecn_agent_set_epc_to_prop_map(0x9D, node->node.base.pmapGet);
445 ecn_agent_set_epc_to_prop_map(0x9E, node->node.base.pmapGet);
446 ecn_agent_set_epc_to_prop_map(0x9F, node->node.base.pmapGet);
447 ecn_agent_queue_init(&node->node.devices);
448 node->node.eobj.profile = &node->node.base.inib;
449 node->node.eobj.eobjs = NULL;
450 node->node.eobj.eobjcnt = pdc / 3;
451 node->state = ecn_node_state_idle;
452 node->timer = TMO_FEVR;
453
454 end = (T_ECN_EOJ *)&edt[pdc];
455 for (eoj = (T_ECN_EOJ *)&edt[1]; eoj < end; eoj++) {
456 ecn_device_t *device;
457 ecn_agent_buffer_t *obj;
458
459 ret = get_buf(agent, &obj);
460 if(ret != E_OK){
461 ECN_DBG_PUT("get_buf");
462 return NULL;
463 }
464
465 memset(obj, 0, sizeof(*obj));
466 device = &obj->cnt.device;
467 device->node = &node->node;
468 device->base.svc = svc;
469 device->base.eobjId = svc->tmax_eobjid + 1 + (((intptr_t)obj - (intptr_t)agent->blockes) / sizeof(agent->blockes[0]));
470 device->base.inib.eobjatr = EOBJ_DEVICE;
471 device->base.inib.enodid = node->node.base.eobjId;
472 device->base.inib.exinf = (intptr_t)device;
473 device->base.inib.eojx1 = eoj->eojx1;
474 device->base.inib.eojx2 = eoj->eojx2;
475 device->base.inib.eojx3 = eoj->eojx3;
476 device->base.inib.eprp = &agent->peprpinib;
477 device->base.inib.eprpcnt = 0;
478 ecn_agent_set_epc_to_prop_map(0x9D, device->base.pmapGet);
479 ecn_agent_set_epc_to_prop_map(0x9E, device->base.pmapGet);
480 ecn_agent_set_epc_to_prop_map(0x9F, device->base.pmapGet);
481
482 ecn_agent_queue_add(&node->node.devices, &obj->hdr.queue);
483 }
484 break;
485 default:
486 continue;
487 }
488 break;
489 }
490
491 if (result == NULL)
492 return NULL;
493
494 ecn_agent_queue_add(&agent->nodes, &result->hdr.queue);
495
496 return node;
497}
498
499static ER ecn_agent_proc_get_device_list(ecnl_svc_task_t *svc, ecn_agent_t *agent, ECN_FBS_ID req)
500{
501 mrb_state *mrb = svc->mrb;
502 ER ret;
503 ECN_FBS_ID res;
504 ecn_inm_get_device_list_req_t msg;
505 ECN_FBS_SSIZE_T len;
506 ecn_agent_buffer_t *pos, *end = &agent->blockes[TNUM_AEOBJID];
507 ecn_inm_get_device_item_t item;
508 int i, j;
509
510 ret = _ecn_fbs_get_data(mrb, req, &msg, sizeof(msg), &len);
511 if (ret != E_OK) {
512 return ret;
513 }
514
515 ret = _ecn_tsk_cre_res_fbs(svc, req, ECN_INM_GET_DEVICE_LIST_RES, &res);
516 if (ret != E_OK) {
517 return ret;
518 }
519
520 ret = _ecn_fbs_add_data_ex(mrb, res, &msg.requestid, sizeof(((ecn_inm_get_device_list_res_t *)0)->requestid));
521 if (ret != E_OK) {
522 _ecn_fbs_del(mrb, res);
523 return ret;
524 }
525
526 for (i = 0; i < svc->tnum_enodid; i++) {
527 const EOBJCB *enod = &svc->eobjcb_table[i];
528 for (j = 0; j < enod->eobjcnt; j++) {
529 const EOBJINIB *eobj = enod->eobjs[i];
530 item.eobjid = echonet_svctask_get_eobjid(svc, eobj);
531 item.enodid = eobj->enodid;
532 item.state = true;
533 item.eojx1 = eobj->eojx1;
534 item.eojx2 = eobj->eojx2;
535 item.eojx3 = eobj->eojx3;
536 item.addrid = (i == 0) ? ENOD_LOCAL_ID : (ENOD_REMOTE_ID + i);
537
538 ret = _ecn_fbs_add_data_ex(mrb, res, &item, sizeof(item));
539 if (ret != E_OK) {
540 _ecn_fbs_del(mrb, res);
541 return ret;
542 }
543 }
544 }
545
546 for (pos = &agent->blockes[0]; pos < end; pos++){
547 if(pos->cnt.obj.eobjId == 0)
548 continue;
549
550 item.eobjid = pos->cnt.obj.eobjId;
551 item.enodid = pos->cnt.obj.inib.enodid;
552 item.state = (pos->cnt.obj.pmapFlag & (PMAP_FLAG_SET | PMAP_FLAG_GET | PMAP_FLAG_ANNO))
553 == (PMAP_FLAG_SET | PMAP_FLAG_GET | PMAP_FLAG_ANNO);
554 item.eojx1 = pos->cnt.obj.inib.eojx1;
555 item.eojx2 = pos->cnt.obj.inib.eojx2;
556 item.eojx3 = pos->cnt.obj.inib.eojx3;
557
558 if(pos->cnt.device.node != NULL)
559 item.addrid = pos->cnt.device.node->enodId;
560 else
561 item.addrid = pos->cnt.node.node.enodId;
562
563 ret = _ecn_fbs_add_data_ex(mrb, res, &item, sizeof(item));
564 if (ret != E_OK) {
565 _ecn_fbs_del(mrb, res);
566 return ret;
567 }
568 }
569
570 ret = ecn_fbs_enqueue(res.ptr->hdr.target.mbxid, res.ptr);
571 if (ret != E_OK) {
572 _ecn_fbs_del(mrb, res);
573 return ret;
574 }
575
576 return E_OK;
577}
578
579static ER ecn_agent_proc_get_device_info(ecnl_svc_task_t *svc, ecn_agent_t *agent, ECN_FBS_ID req)
580{
581 mrb_state *mrb = svc->mrb;
582 ER ret;
583 ECN_FBS_ID res;
584 ecn_inm_get_device_info_req_t msg;
585 ecn_inm_get_device_info_res_t rmsg;
586 ECN_FBS_SSIZE_T len;
587
588 ret = _ecn_fbs_get_data(mrb, req, &msg, sizeof(msg), &len);
589 if (ret != E_OK) {
590 return ret;
591 }
592
593 memset(&rmsg, 0, sizeof(rmsg));
594
595 if (msg.eobjid <= svc->tmax_eobjid) {
596 const EOBJINIB *eobj = echonet_svctask_get_eobjinib(svc, msg.eobjid);
597 int i;
598
599 rmsg.requestid = msg.requestid;
600 rmsg.eobjid = msg.eobjid;
601 for (i = 0; i < eobj->eprpcnt; i++) {
602 uint8_t epc = eobj->eprp[i]->eprpcd;
603 ecn_agent_set_epc_to_prop_map(epc, rmsg.pmapSet);
604 ecn_agent_set_epc_to_prop_map(epc, rmsg.pmapGet);
605 ecn_agent_set_epc_to_prop_map(epc, rmsg.pmapAnno);
606 }
607 rmsg.eprpcnt = eobj->eprpcnt;
608 }
609 else {
610 int eobjId;
611 ecn_agent_buffer_t *pos;
612
613 eobjId = msg.eobjid - svc->tmax_eobjid - 1;
614 pos = &agent->blockes[eobjId];
615
616 rmsg.requestid = msg.requestid;
617 rmsg.eobjid = pos->cnt.obj.eobjId;
618 memcpy(rmsg.pmapSet, pos->cnt.obj.pmapSet, sizeof(rmsg.pmapSet));
619 memcpy(rmsg.pmapGet, pos->cnt.obj.pmapGet, sizeof(rmsg.pmapGet));
620 memcpy(rmsg.pmapAnno, pos->cnt.obj.pmapAnno, sizeof(rmsg.pmapAnno));
621 rmsg.eprpcnt = pos->cnt.obj.eprpcnt;
622 }
623
624 ret = _ecn_tsk_cre_res_fbs(svc, req, ECN_INM_GET_DEVICE_INFO_RES, &res);
625 if (ret != E_OK) {
626 return ret;
627 }
628
629 ret = _ecn_fbs_add_data_ex(mrb, res, &rmsg, sizeof(rmsg));
630 if (ret != E_OK) {
631 _ecn_fbs_del(mrb, res);
632 return ret;
633 }
634
635 ret = ecn_fbs_enqueue(res.ptr->hdr.target.mbxid, res.ptr);
636 if (ret != E_OK) {
637 _ecn_fbs_del(mrb, res);
638 return ret;
639 }
640
641 return E_OK;
642}
643
644TMO ecn_agent_get_timer(ecnl_svc_task_t *svc)
645{
646 TMO timer = TMO_FEVR, temp;
647 ecn_agent_t *agent = &svc->agent;
648 ecn_node_agent_t *node;
649 ecn_agent_queue_t *queue;
650
651 queue = &agent->nodes;
652 for (;;) {
653 queue = queue->p_next;
654#ifdef _DEBUG
655 assert(queue->p_parent == &agent->nodes);
656#endif
657 if(&agent->nodes == queue)
658 break;
659
660 node = (ecn_node_agent_t *)cast_obj(queue);
661 temp = node->timer;
662 if (temp != TMO_FEVR) {
663 if ((timer == TMO_FEVR) || (temp < timer)) {
664 timer = temp;
665 }
666 }
667 }
668
669 return timer;
670}
671
672void ecn_agent_progress(ecnl_svc_task_t *svc, TMO interval)
673{
674 ecn_agent_t *agent = &svc->agent;
675 ecn_node_agent_t *node;
676 ecn_agent_queue_t *queue;
677
678 queue = &agent->nodes;
679 for (;;) {
680 queue = queue->p_next;
681#ifdef _DEBUG
682 assert(queue->p_parent == &agent->nodes);
683#endif
684 if(&agent->nodes == queue)
685 break;
686
687 node = (ecn_node_agent_t *)cast_obj(queue);
688 if (node->timer == TMO_FEVR)
689 continue;
690
691 node->timer -= interval;
692 if (node->timer <= 0) {
693 node->timer = 0;
694 }
695 }
696}
697
698void ecn_agent_timeout(ecnl_svc_task_t *svc)
699{
700 ecn_agent_t *agent = &svc->agent;
701 ecn_node_agent_t *node;
702 ecn_agent_queue_t *queue;
703
704 queue = &agent->nodes;
705 for (;;) {
706 queue = queue->p_next;
707#ifdef _DEBUG
708 assert(queue->p_parent == &agent->nodes);
709#endif
710 if(&agent->nodes == queue)
711 break;
712
713 node = (ecn_node_agent_t *)cast_obj(queue);
714 if (node->timer != 0)
715 continue;
716
717 switch (node->state) {
718 case ecn_node_state_start:
719 ecn_node_timeout_on_start(svc, node);
720 break;
721 case ecn_node_state_set_prpmap_wait:
722 ecn_node_timeout_on_set_prpmap_wait(svc, node);
723 break;
724 case ecn_node_state_get_prpmap_wait:
725 ecn_node_timeout_on_get_prpmap_wait(svc, node);
726 break;
727 case ecn_node_state_anno_prpmap_wait:
728 ecn_node_timeout_on_anno_prpmap_wait(svc, node);
729 break;
730 case ecn_node_state_fault:
731 ecn_node_timeout_on_start(svc, node);
732 break;
733 default:
734#ifdef _DEBUG
735 assert(0);
736#endif
737 break;
738 }
739 }
740}
741
742bool_t ecn_agent_proc_int_msg(ecnl_svc_task_t *svc, ECN_FBS_ID fbs, uint8_t cmd)
743{
744 ecn_agent_t *agent = &svc->agent;
745
746 switch(cmd)
747 {
748 case ECN_INM_GET_DEVICE_LIST_REQ:
749 ecn_agent_proc_get_device_list(svc, agent, fbs);
750 break;
751 case ECN_INM_GET_DEVICE_INFO_REQ:
752 ecn_agent_proc_get_device_info(svc, agent, fbs);
753 break;
754 default:
755 return false;
756 }
757
758 return true;
759}
760
761void ecn_agent_proc_ecn_msg(ecnl_svc_task_t *svc, const EOBJCB **ppk_snod, const EOBJINIB **ppk_sobj, T_EDATA *esv)
762{
763 ecn_agent_t *agent = &svc->agent;
764 ecn_node_agent_t *snod;
765 ecn_obj_t *sobj;
766
767 /* 静的に定義された送信å…
768ƒã®å ´åˆ */
769 if ((*ppk_snod != NULL) && (*ppk_snod)->eobjs != NULL) {
770 /* 処理しない */
771 return;
772 }
773
774 snod = ecn_agent_find_node2(svc, *ppk_snod);
775
776 /* 送信å…
777ƒã‚’知らなかったら */
778 if (snod == NULL) {
779 /* 送信å…
780ƒã®ãƒŽãƒ¼ãƒ‰æƒ…
781報を新規に作成 */
782 snod = ecn_agent_create_node(svc, agent, esv);
783 if (snod == NULL)
784 return;
785 }
786
787 sobj = ecn_agent_find_obj2(snod, *ppk_sobj);
788
789 /* ノードプロファイルの場合 */
790 if ((esv->hdr.edata.seoj.eojx1 == EOJ_X1_PROFILE)
791 && (esv->hdr.edata.seoj.eojx2 == EOJ_X2_NODE_PROFILE)) {
792 sobj = &snod->node.base;
793 }
794 /* 機器オブジェクトの場合 */
795 else {
796 sobj = ecn_agent_find_eobj(&snod->node.eobj, esv->hdr.edata.seoj);
797 }
798
799 *ppk_snod = &snod->node.eobj;
800 *ppk_sobj = &sobj->inib;
801
802 agent->current_node = snod;
803 agent->msg_proced = false;
804}
805
806void ecn_agent_proc_ecn_msg_end(ecnl_svc_task_t *svc)
807{
808 ecn_agent_t *agent = &svc->agent;
809 ecn_node_agent_t *node = agent->current_node;
810 ecn_obj_t *sobj;
811
812 if(node == NULL)
813 return;
814
815 sobj = node->current;
816 if(sobj == NULL)
817 return;
818
819 if (agent->msg_proced) {
820 switch (node->state) {
821 case ecn_node_state_set_prpmap_wait:
822 ecn_node_next_proc_on_set_prpmap_wait(svc, node, sobj);
823 break;
824 case ecn_node_state_get_prpmap_wait:
825 ecn_node_next_proc_on_get_prpmap_wait(svc, node, sobj);
826 break;
827 case ecn_node_state_anno_prpmap_wait:
828 ecn_node_next_proc_on_anno_prpmap_wait(svc, node, sobj);
829 break;
830 }
831 }
832}
833
834static void ecn_node_send_set_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
835{
836 T_EDATA *esv;
837 ecn_obj_t *obj = node->current;
838
839 // プロパティ値読み出し要求
840 ecn_esv_get(svc, &esv, obj->eobjId, 0x9E);
841 ecn_snd_esv(svc, esv);
842
843 node->state = ecn_node_state_set_prpmap_wait;
844 node->timer = (TMO)5000;
845}
846
847static void ecn_node_send_get_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
848{
849 T_EDATA *esv;
850 ecn_obj_t *obj = node->current;
851
852 // プロパティ値読み出し要求
853 ecn_esv_get(svc, &esv, obj->eobjId, 0x9F);
854 ecn_snd_esv(svc, esv);
855
856 node->state = ecn_node_state_get_prpmap_wait;
857 node->timer = (TMO)5000;
858}
859
860static void ecn_node_send_anno_prop_map(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
861{
862 T_EDATA *esv;
863 ecn_obj_t *obj = node->current;
864
865 // プロパティ値読み出し要求
866 ecn_esv_get(svc, &esv, obj->eobjId, 0x9D);
867 ecn_snd_esv(svc, esv);
868
869 node->state = ecn_node_state_anno_prpmap_wait;
870 node->timer = (TMO)5000;
871}
872
873static void ecn_node_next_obj(ecn_node_agent_t *node)
874{
875 ecn_obj_t *obj = node->current;
876 ecn_agent_queue_t *queue;
877 ecn_device_t *device;
878
879 /* objが指定されていない場合 */
880 if(obj == NULL){
881 /* このノードを返す */
882 node->current = &node->node.base;
883 return;
884 }
885 /* ノードの場合 */
886 else if((obj->inib.eojx1 == EOJ_X1_PROFILE) && (obj->inib.eojx2 == EOJ_X2_NODE_PROFILE)){
887 node = (ecn_node_agent_t *)obj;
888
889 /* é…
890ä¸‹ã®æ©Ÿå™¨ã‚’返す */
891 queue = node->node.devices.p_next;
892 device = (ecn_device_t *)cast_obj(queue);
893 }
894 /* 機器の場合 */
895 else{
896 /* 次の機器を返す */
897 node = (ecn_node_agent_t *)((ecn_device_t *)obj)->node;
898 queue = cast_queue(obj)->p_next;
899 device = (ecn_device_t *)cast_obj(queue);
900 }
901
902 /* その機器が末尾だった場合 */
903 if(&node->node.devices == queue){
904 node->current = NULL;
905 }
906 else {
907 node->current = &device->base;
908 }
909}
910
911static void ecn_node_timeout_on_start(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
912{
913 for (;;) {
914 ecn_obj_t *obj = node->current;
915 if (obj == NULL) {
916 node->state = ecn_node_state_idle;
917 node->timer = TMO_FEVR;
918 return;
919 }
920
921 if((obj->pmapFlag & PMAP_FLAG_SET) == 0){
922 ecn_node_send_set_prop_map(svc, node);
923 break;
924 }
925 else if((obj->pmapFlag & PMAP_FLAG_GET) == 0){
926 ecn_node_send_get_prop_map(svc, node);
927 break;
928 }
929 else if((obj->pmapFlag & PMAP_FLAG_ANNO) == 0){
930 ecn_node_send_anno_prop_map(svc, node);
931 break;
932 }
933 else{
934 ecn_node_next_obj(node);
935 }
936 }
937}
938
939static void ecn_node_next_proc_on_set_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj)
940{
941 if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
942 ecn_node_send_get_prop_map(svc, node);
943 }
944 else if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
945 ecn_node_send_anno_prop_map(svc, node);
946 }
947 else if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
948 ecn_node_send_set_prop_map(svc, node);
949 }
950 else{
951 ecn_node_next_obj(node);
952 ecn_node_timeout_on_start(svc, node);
953 }
954}
955
956static void ecn_node_timeout_on_set_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
957{
958 ecn_obj_t *obj = node->current;
959 if(obj == NULL){
960 node->state = ecn_node_state_idle;
961 node->timer = TMO_FEVR;
962 return;
963 }
964
965 node->retry++;
966 if(node->retry < 3){
967 ecn_node_next_proc_on_set_prpmap_wait(svc, node, obj);
968 }
969 else{
970 node->retry = 0;
971 node->state = ecn_node_state_fault;
972 node->timer = TMO_FEVR;
973 }
974}
975
976static void ecn_node_next_proc_on_get_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj)
977{
978 if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
979 ecn_node_send_anno_prop_map(svc, node);
980 }
981 else if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
982 ecn_node_send_set_prop_map(svc, node);
983 }
984 else if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
985 ecn_node_send_get_prop_map(svc, node);
986 }
987 else{
988 ecn_node_next_obj(node);
989 ecn_node_timeout_on_start(svc, node);
990 }
991}
992
993static void ecn_node_timeout_on_get_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
994{
995 ecn_obj_t *obj = node->current;
996 if(obj == NULL){
997 node->state = ecn_node_state_idle;
998 node->timer = TMO_FEVR;
999 return;
1000 }
1001
1002 ecn_node_next_proc_on_get_prpmap_wait(svc, node, obj);
1003}
1004
1005static void ecn_node_next_proc_on_anno_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node, ecn_obj_t *sobj)
1006{
1007 if((sobj->pmapFlag & PMAP_FLAG_SET) == 0){
1008 ecn_node_send_set_prop_map(svc, node);
1009 }
1010 else if((sobj->pmapFlag & PMAP_FLAG_GET) == 0){
1011 ecn_node_send_get_prop_map(svc, node);
1012 }
1013 else if((sobj->pmapFlag & PMAP_FLAG_ANNO) == 0){
1014 ecn_node_send_anno_prop_map(svc, node);
1015 }
1016 else{
1017 ecn_node_next_obj(node);
1018 ecn_node_timeout_on_start(svc, node);
1019 }
1020}
1021
1022static void ecn_node_timeout_on_anno_prpmap_wait(ecnl_svc_task_t *svc, ecn_node_agent_t *node)
1023{
1024 ecn_obj_t *obj = node->current;
1025 if(obj == NULL){
1026 node->state = ecn_node_state_idle;
1027 node->timer = TMO_FEVR;
1028 return;
1029 }
1030
1031 ecn_node_next_proc_on_anno_prpmap_wait(svc, node, obj);
1032}
1033
1034const EPRPINIB *ecn_agent_get_property(const EOBJINIB *fp_obj, uint8_t fa_epc, const EPRPINIB *item)
1035{
1036 ecn_obj_t *obj = cast_obj2(fp_obj);
1037 bool_t has = false;
1038
1039 /* ノードの場合はインスタンスリスト通知と自ノードインスタンスリストS通知を必
1040須で受け取る */
1041 if ((fp_obj->enodid == 0) && ((fa_epc == 0xD5) || (fa_epc == 0xD6)))
1042 has = true;
1043 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapGet))
1044 has = true;
1045 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapSet))
1046 has = true;
1047 else if (ecn_agent_contains_epc_in_prop_map(fa_epc, obj->pmapAnno))
1048 has = true;
1049
1050 if(!has)
1051 return NULL;
1052
1053 ((EPRPINIB *)item)->eprpcd = fa_epc;
1054 ((EPRPINIB *)item)->exinf = (intptr_t)fp_obj;
1055
1056 return item;
1057}
1058
1059int ecn_agent_eprpget(ecnl_svc_task_t *svc, const EPRPINIB *item, void *dst, int size)
1060{
1061 return 0;
1062}
1063
1064int ecn_agent_eprpset(ecnl_svc_task_t *svc, const EPRPINIB *item, const void *src, int size, bool_t *anno)
1065{
1066 ecn_agent_t *agent = cast_agent(item);
1067 ecn_node_agent_t *node = agent->current_node;
1068 const uint8_t *edt = (const uint8_t *)src;
1069 ecn_obj_t *sobj = cast_obj2((const EOBJINIB *)item->exinf);
1070 uint8_t eprpcnt;
1071 int i;
1072
1073 switch (item->eprpcd) {
1074 /* インスタンスリスト通知の場合 */
1075 case 0xD5:
1076 /* 自ノードインスタンスリストS通知の場合 */
1077 case 0xD6:
1078 if ((node != NULL) && (node->state == ecn_node_state_idle)) {
1079 ecn_agent_queue_t *devices = &node->node.devices;
1080 ecn_agent_queue_t *queue = devices->p_next;
1081#ifdef _DEBUG
1082 assert(queue->p_parent == devices);
1083#endif
1084 for (; queue != devices; queue = queue->p_next) {
1085 ecn_obj_t *obj = cast_obj(queue);
1086 obj->pmapFlag = 0;
1087 }
1088 node->node.base.pmapFlag = 0;
1089 node->state = ecn_node_state_start;
1090 node->timer = (TMO)1000;
1091 node->current = sobj;
1092 }
1093 break;
1094 /* 通知プロパティマップの場合 */
1095 case 0x9D:
1096 eprpcnt = edt[0];
1097
1098 if (eprpcnt < 16) {
1099 /* サイズチェック */
1100 if (eprpcnt + 1 != size)
1101 return 0;
1102
1103 for (i = 1; i < size; i++)
1104 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapAnno);
1105 }
1106 else {
1107 /* サイズチェック */
1108 if (size != 17)
1109 return 0;
1110
1111 memcpy(sobj->pmapAnno, &edt[1], 16);
1112 }
1113 sobj->eprpcnt = eprpcnt;
1114 sobj->pmapFlag |= PMAP_FLAG_ANNO;
1115 break;
1116 /* SETプロパティマップの場合 */
1117 case 0x9E:
1118 eprpcnt = edt[0];
1119
1120 if (eprpcnt < 16) {
1121 /* サイズチェック */
1122 if (eprpcnt + 1 != size)
1123 return 0;
1124
1125 for (i = 1; i < size; i++)
1126 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapSet);
1127 }
1128 else {
1129 /* サイズチェック */
1130 if (size != 17)
1131 return 0;
1132
1133 memcpy(sobj->pmapSet, &edt[1], 16);
1134 }
1135 sobj->eprpcnt = eprpcnt;
1136 sobj->pmapFlag |= PMAP_FLAG_SET;
1137 break;
1138 /* GETプロパティマップの場合 */
1139 case 0x9F:
1140 eprpcnt = edt[0];
1141
1142 if (eprpcnt < 16) {
1143 /* サイズチェック */
1144 if (eprpcnt + 1 != size)
1145 return 0;
1146
1147 for (i = 1; i < size; i++)
1148 ecn_agent_set_epc_to_prop_map(edt[i], sobj->pmapGet);
1149 }
1150 else {
1151 /* サイズチェック */
1152 if (size != 17)
1153 return 0;
1154
1155 memcpy(sobj->pmapGet, &edt[1], 16);
1156 }
1157 sobj->eprpcnt = eprpcnt;
1158 sobj->pmapFlag |= PMAP_FLAG_GET;
1159 break;
1160 default:
1161 svc->forward_esv = true;
1162 return 0;
1163 }
1164
1165 agent->msg_proced = true;
1166
1167 return size;
1168}
1169
1170ER ecn_agent_get_device_list(ecnl_svc_task_t *svc, T_ECN_FBS_QUEUE *sender, int requestid, ECN_FBS_ID *pk_req)
1171{
1172 mrb_state *mrb = svc->mrb;
1173 ER a_ret;
1174 ECN_FBS_ID req;
1175
1176 a_ret = _ecn_tsk_cre_req_fbs(svc, sender, ECN_INM_GET_DEVICE_LIST_REQ, &req);
1177 if (a_ret != E_OK) {
1178 return a_ret;
1179 }
1180
1181 a_ret = _ecn_fbs_add_data_ex(mrb, req, &requestid, sizeof(((ecn_inm_get_device_list_req_t *)0)->requestid));
1182 if (a_ret != E_OK) {
1183 _ecn_fbs_del(mrb, req);
1184 return a_ret;
1185 }
1186
1187 *pk_req = req;
1188
1189 return E_OK;
1190}
1191
1192ER ecn_agent_get_device_info(ecnl_svc_task_t *svc, T_ECN_FBS_QUEUE *sender, int requestid, ID eobjid, ECN_FBS_ID *pk_req)
1193{
1194 mrb_state *mrb = svc->mrb;
1195 ER a_ret;
1196 ECN_FBS_ID req;
1197
1198 a_ret = _ecn_tsk_cre_req_fbs(svc, sender, ECN_INM_GET_DEVICE_INFO_REQ, &req);
1199 if (a_ret != E_OK) {
1200 return a_ret;
1201 }
1202
1203 a_ret = _ecn_fbs_add_data_ex(mrb, req, &requestid, sizeof(((ecn_inm_get_device_info_req_t *)0)->requestid));
1204 if (a_ret != E_OK) {
1205 _ecn_fbs_del(mrb, req);
1206 return a_ret;
1207 }
1208
1209 a_ret = _ecn_fbs_add_data_ex(mrb, req, &eobjid, sizeof(((ecn_inm_get_device_info_req_t *)0)->eobjid));
1210 if (a_ret != E_OK) {
1211 _ecn_fbs_del(mrb, req);
1212 return a_ret;
1213 }
1214
1215 *pk_req = req;
1216
1217 return E_OK;
1218}
Note: See TracBrowser for help on using the repository browser.