1 /*
2  * Copyright (C) 2018-2020 Alibaba Group Holding Limited
3  */
4 
5 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
6 #include <api/mesh.h>
7 #include "sig_models/sig_model.h"
8 
9 #include "access.h"
10 #include "common/log.h"
11 
12 struct bt_mesh_model_pub g_scene_pub = {
13     .msg = NET_BUF_SIMPLE(2 + 5 + 4),
14 };
15 
_scene_prepare_buf(struct bt_mesh_model * p_model,struct net_buf_simple * p_msg,bool is_ack)16 static void _scene_prepare_buf(struct bt_mesh_model *p_model, struct net_buf_simple *p_msg, bool is_ack)
17 {
18     sig_model_state_t *p_state = &((sig_model_element_state_t *)p_model->user_data)->state;
19 
20     bt_mesh_model_msg_init(p_msg, OP_GENERIC_SCENE_STATUS);
21     net_buf_simple_add_le16(p_msg, p_state->scene[TYPE_PRESENT]);
22 }
23 
_scene_status(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,bool is_ack)24 static void _scene_status(struct bt_mesh_model *p_model,
25                           struct bt_mesh_msg_ctx *p_ctx, bool is_ack)
26 {
27     struct net_buf_simple *p_msg = NET_BUF_SIMPLE(1 + 2 + 4);
28 
29     BT_DBG("addr(0x%04x)", bt_mesh_model_elem(p_model)->addr);
30 
31     _scene_prepare_buf(p_model, p_msg, is_ack);
32     p_ctx->send_ttl = GENIE_TRANSPORT_DEFAULT_TTL;
33     if (bt_mesh_model_send(p_model, p_ctx, p_msg, NULL, NULL))
34     {
35         BT_ERR("Unable to send scene Status");
36     }
37     BT_DBG("Success!!!");
38 }
39 
genie_model_scene_changed(u16_t last_scene,u16_t target_scene)40 int genie_model_scene_changed(u16_t last_scene, u16_t target_scene)
41 {
42     return 0;
43 }
44 
_scene_analyze(struct bt_mesh_model * p_model,u16_t src_addr,struct net_buf_simple * p_buf)45 static E_MESH_ERROR_TYPE _scene_analyze(struct bt_mesh_model *p_model,
46                                         u16_t src_addr, struct net_buf_simple *p_buf)
47 {
48     s16_t scene = 0;
49     u8_t tid = 0;
50     sig_model_element_state_t *p_elem = NULL;
51 
52     if (!p_model || !p_buf)
53         return MESH_ANALYZE_ARGS_ERROR;
54 
55     p_elem = p_model->user_data;
56 
57     if (p_buf->len != 3 && p_buf->len != 5)
58     {
59         BT_ERR("MESH_ANALYZE_SIZE_ERROR buf->len(%d)", p_buf->len);
60         return MESH_ANALYZE_SIZE_ERROR;
61     }
62 
63     scene = (s16_t)net_buf_simple_pull_le16(p_buf);
64     tid = net_buf_simple_pull_u8(p_buf);
65 
66     if (genie_transport_check_tid(src_addr, tid, p_elem->element_id) != MESH_SUCCESS)
67     {
68         BT_ERR("MESH_TID_REPEAT src_addr(0x%04x) tid(0x%02x)", src_addr, tid);
69         return MESH_TID_REPEAT;
70     }
71     genie_transport_src_addr_set(src_addr);
72 
73     if (p_elem->state.scene[TYPE_TARGET] != scene)
74     {
75         genie_model_scene_changed(p_elem->state.scene[TYPE_TARGET], scene);
76         p_elem->state.scene[TYPE_TARGET] = scene;
77         sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_SCENE);
78     }
79     else
80     {
81         GENIE_LOG_WARN("Dup light sence");
82     }
83 
84     GENIE_LOG_INFO("light sence(0x%02x)", p_elem->state.scene);
85 
86     return MESH_SUCCESS;
87 }
88 
_scene_get(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)89 static void _scene_get(struct bt_mesh_model *p_model,
90                        struct bt_mesh_msg_ctx *p_ctx,
91                        struct net_buf_simple *p_buf)
92 {
93     sig_model_msg msg;
94     sig_model_element_state_t *p_elem_state = NULL;
95 
96     memset(&msg, 0, sizeof(sig_model_msg));
97     msg.opcode = OP_GENERIC_SCENE_GET;
98 
99     if (p_buf != NULL)
100     {
101         msg.len = p_buf->len;
102         msg.data = (u8_t *)p_buf->data;
103     }
104     genie_transport_src_addr_set(p_ctx->addr);
105 
106     p_elem_state = (sig_model_element_state_t *)p_model->user_data;
107     msg.element_id = p_elem_state->element_id;
108     sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
109 
110 #ifndef CONFIG_GENIE_MESH_NO_AUTO_REPLY
111     _scene_status(p_model, p_ctx, 0);
112 #endif
113 }
114 
_scene_set(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)115 static void _scene_set(struct bt_mesh_model *p_model,
116                        struct bt_mesh_msg_ctx *p_ctx,
117                        struct net_buf_simple *p_buf)
118 {
119     sig_model_msg msg;
120     sig_model_element_state_t *p_elem_state = NULL;
121 
122     memset(&msg, 0, sizeof(sig_model_msg));
123     msg.opcode = OP_GENERIC_SCENE_SET;
124     if (p_buf != NULL)
125     {
126         msg.len = p_buf->len;
127         msg.data = (u8_t *)p_buf->data;
128     }
129 
130     E_MESH_ERROR_TYPE ret = _scene_analyze(p_model, p_ctx->addr, p_buf);
131 
132     BT_DBG("ret %d", ret);
133 
134     if (ret == MESH_SUCCESS)
135     {
136         p_elem_state = (sig_model_element_state_t *)p_model->user_data;
137         msg.element_id = p_elem_state->element_id;
138         sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
139     }
140 
141 #ifndef CONFIG_GENIE_MESH_NO_AUTO_REPLY
142     if (ret == MESH_SUCCESS || ret == MESH_TID_REPEAT)
143     {
144         _scene_status(p_model, p_ctx, 1);
145         if (ret == MESH_SUCCESS)
146         {
147             sig_model_event(SIG_MODEL_EVT_ANALYZE_MSG, (sig_model_element_state_t *)p_model->user_data);
148         }
149     }
150 #endif
151 }
152 
_scene_set_unack(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)153 static void _scene_set_unack(struct bt_mesh_model *p_model,
154                              struct bt_mesh_msg_ctx *p_ctx,
155                              struct net_buf_simple *p_buf)
156 {
157     sig_model_msg msg;
158     sig_model_element_state_t *p_elem_state = NULL;
159 
160     memset(&msg, 0, sizeof(sig_model_msg));
161     msg.opcode = OP_GENERIC_SCENE_SET_UNACK;
162     if (p_buf != NULL)
163     {
164         msg.len = p_buf->len;
165         msg.data = (u8_t *)p_buf->data;
166     }
167 
168     E_MESH_ERROR_TYPE ret = _scene_analyze(p_model, p_ctx->addr, p_buf);
169 
170     if (ret == MESH_SUCCESS)
171     {
172         p_elem_state = (sig_model_element_state_t *)p_model->user_data;
173         msg.element_id = p_elem_state->element_id;
174         sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
175 #ifndef CONFIG_GENIE_MESH_NO_AUTO_REPLY
176         sig_model_event(SIG_MODEL_EVT_ANALYZE_MSG, (sig_model_element_state_t *)p_model->user_data);
177 #endif
178     }
179 }
180 
181 const struct bt_mesh_model_op g_scene_op[GENIE_SCENE_OP_NUM] = {
182     {OP_GENERIC_SCENE_GET, 0, _scene_get},
183     {OP_GENERIC_SCENE_SET, 2, _scene_set},
184     {OP_GENERIC_SCENE_SET_UNACK, 2, _scene_set_unack},
185     BT_MESH_MODEL_OP_END,
186 };
187