George Djabarov / Mbed OS mbed-os-example-mesh-minimal
Committer:
mbed_official
Date:
Fri Oct 06 03:00:19 2017 +0100
Revision:
59:3e1533ffb4f5
Parent:
54:34cbb2c2155c
Child:
66:30f2c1317e6d
Make our own multicast group and join it.

Do not rely on any default multicast groups to be enabled.
Don't spam nodes which have not joined our group.

Fixes #130

.
Commit copied from https://github.com/ARMmbed/mbed-os-example-mesh-minimal

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 52:27692043e962 1 /*
mbed_official 52:27692043e962 2 * Copyright (c) 2016 ARM Limited. All rights reserved.
mbed_official 52:27692043e962 3 * SPDX-License-Identifier: Apache-2.0
mbed_official 52:27692043e962 4 * Licensed under the Apache License, Version 2.0 (the License); you may
mbed_official 52:27692043e962 5 * not use this file except in compliance with the License.
mbed_official 52:27692043e962 6 * You may obtain a copy of the License at
mbed_official 52:27692043e962 7 *
mbed_official 52:27692043e962 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 52:27692043e962 9 *
mbed_official 52:27692043e962 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 52:27692043e962 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
mbed_official 52:27692043e962 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 52:27692043e962 13 * See the License for the specific language governing permissions and
mbed_official 52:27692043e962 14 * limitations under the License.
mbed_official 52:27692043e962 15 */
mbed_official 52:27692043e962 16 #include "mbed.h"
mbed_official 52:27692043e962 17 #include "nanostack/socket_api.h"
mbed_official 52:27692043e962 18 #include "mesh_led_control_example.h"
mbed_official 52:27692043e962 19 #include "common_functions.h"
mbed_official 52:27692043e962 20 #include "ip6string.h"
mbed_official 52:27692043e962 21 #include "mbed-trace/mbed_trace.h"
mbed_official 52:27692043e962 22
mbed_official 52:27692043e962 23 static void init_socket();
mbed_official 52:27692043e962 24 static void handle_socket();
mbed_official 52:27692043e962 25 static void receive();
mbed_official 52:27692043e962 26 static void my_button_isr();
mbed_official 52:27692043e962 27 static void send_message();
mbed_official 52:27692043e962 28 static void blink();
mbed_official 52:27692043e962 29 static void update_state(uint8_t state);
mbed_official 52:27692043e962 30 static void handle_message(char* msg);
mbed_official 52:27692043e962 31
mbed_official 59:3e1533ffb4f5 32 #define multicast_addr_str "ff15::810a:64d1"
mbed_official 52:27692043e962 33 #define TRACE_GROUP "example"
mbed_official 52:27692043e962 34 #define UDP_PORT 1234
mbed_official 52:27692043e962 35 #define MESSAGE_WAIT_TIMEOUT (30.0)
mbed_official 52:27692043e962 36 #define MASTER_GROUP 0
mbed_official 52:27692043e962 37 #define MY_GROUP 1
mbed_official 52:27692043e962 38
mbed_official 52:27692043e962 39 DigitalOut led_1(MBED_CONF_APP_LED, 1);
mbed_official 52:27692043e962 40 InterruptIn my_button(MBED_CONF_APP_BUTTON);
mbed_official 52:27692043e962 41 DigitalOut output(D3, 1);
mbed_official 52:27692043e962 42 Timeout messageTimeout;
mbed_official 52:27692043e962 43
mbed_official 52:27692043e962 44 NetworkInterface * network_if;
mbed_official 52:27692043e962 45 UDPSocket* my_socket;
mbed_official 52:27692043e962 46 // queue for sending messages from button press.
mbed_official 52:27692043e962 47 EventQueue queue;
mbed_official 52:27692043e962 48 // for LED blinking
mbed_official 52:27692043e962 49 Ticker ticker;
mbed_official 52:27692043e962 50
mbed_official 52:27692043e962 51 uint8_t multi_cast_addr[16] = {0};
mbed_official 52:27692043e962 52 uint8_t receive_buffer[20];
mbed_official 52:27692043e962 53 // how many hops the multicast message can go
mbed_official 52:27692043e962 54 static const int16_t multicast_hops = 10;
mbed_official 52:27692043e962 55 bool button_status = 0;
mbed_official 52:27692043e962 56
mbed_official 52:27692043e962 57 void start_mesh_led_control_example(NetworkInterface * interface){
mbed_official 52:27692043e962 58 tr_debug("start_mesh_led_control_example()");
mbed_official 52:27692043e962 59 MBED_ASSERT(MBED_CONF_APP_LED != NC);
mbed_official 52:27692043e962 60 MBED_ASSERT(MBED_CONF_APP_BUTTON != NC);
mbed_official 52:27692043e962 61
mbed_official 52:27692043e962 62 network_if = interface;
mbed_official 52:27692043e962 63 stoip6(multicast_addr_str, strlen(multicast_addr_str), multi_cast_addr);
mbed_official 52:27692043e962 64 init_socket();
mbed_official 52:27692043e962 65 }
mbed_official 52:27692043e962 66
mbed_official 52:27692043e962 67 static void messageTimeoutCallback()
mbed_official 52:27692043e962 68 {
mbed_official 52:27692043e962 69 send_message();
mbed_official 52:27692043e962 70 }
mbed_official 52:27692043e962 71
mbed_official 52:27692043e962 72 static void blink() {
mbed_official 52:27692043e962 73 led_1 = !led_1;
mbed_official 52:27692043e962 74 }
mbed_official 52:27692043e962 75
mbed_official 52:27692043e962 76 void start_blinking() {
mbed_official 52:27692043e962 77 ticker.attach(blink, 1.0);
mbed_official 52:27692043e962 78 }
mbed_official 52:27692043e962 79
mbed_official 52:27692043e962 80 void cancel_blinking() {
mbed_official 52:27692043e962 81 ticker.detach();
mbed_official 52:27692043e962 82 led_1=1;
mbed_official 52:27692043e962 83 }
mbed_official 52:27692043e962 84
mbed_official 52:27692043e962 85 static void send_message() {
mbed_official 52:27692043e962 86 tr_debug("send msg %d", button_status);
mbed_official 52:27692043e962 87
mbed_official 52:27692043e962 88 char buf[20];
mbed_official 52:27692043e962 89 int length;
mbed_official 52:27692043e962 90
mbed_official 52:27692043e962 91 /**
mbed_official 52:27692043e962 92 * Multicast control message is a NUL terminated string of semicolon separated
mbed_official 52:27692043e962 93 * <field identifier>:<value> pairs.
mbed_official 52:27692043e962 94 *
mbed_official 52:27692043e962 95 * Light control message format:
mbed_official 52:27692043e962 96 * t:lights;g:<group_id>;s:<1|0>;\0
mbed_official 52:27692043e962 97 */
mbed_official 52:27692043e962 98 length = snprintf(buf, sizeof(buf), "t:lights;g:%03d;s:%s;", MY_GROUP, (button_status ? "1" : "0")) + 1;
mbed_official 52:27692043e962 99 MBED_ASSERT(length > 0);
mbed_official 52:27692043e962 100 tr_debug("Sending lightcontrol message, %d bytes: %s", length, buf);
mbed_official 52:27692043e962 101 SocketAddress send_sockAddr(multi_cast_addr, NSAPI_IPv6, UDP_PORT);
mbed_official 52:27692043e962 102 my_socket->sendto(send_sockAddr, buf, 20);
mbed_official 52:27692043e962 103 //After message is sent, it is received from the network
mbed_official 52:27692043e962 104 }
mbed_official 52:27692043e962 105
mbed_official 52:27692043e962 106 // As this comes from isr, we cannot use printing or network functions directly from here.
mbed_official 52:27692043e962 107 static void my_button_isr() {
mbed_official 52:27692043e962 108 button_status = !button_status;
mbed_official 52:27692043e962 109 queue.call(send_message);
mbed_official 52:27692043e962 110 }
mbed_official 52:27692043e962 111
mbed_official 52:27692043e962 112 static void update_state(uint8_t state) {
mbed_official 52:27692043e962 113 if (state == 1) {
mbed_official 52:27692043e962 114 tr_debug("Turning led on\n");
mbed_official 52:27692043e962 115 led_1 = 0;
mbed_official 52:27692043e962 116 button_status=1;
mbed_official 52:27692043e962 117 output = 0;
mbed_official 52:27692043e962 118 }
mbed_official 52:27692043e962 119 else {
mbed_official 52:27692043e962 120 tr_debug("Turning led off\n");
mbed_official 52:27692043e962 121 led_1 = 1;
mbed_official 52:27692043e962 122 button_status=0;
mbed_official 52:27692043e962 123 output = 1;
mbed_official 52:27692043e962 124 }
mbed_official 52:27692043e962 125 }
mbed_official 52:27692043e962 126
mbed_official 52:27692043e962 127 static void handle_message(char* msg) {
mbed_official 52:27692043e962 128 // Check if this is lights message
mbed_official 52:27692043e962 129 uint8_t state=button_status;
mbed_official 52:27692043e962 130 uint16_t group=0xffff;
mbed_official 52:27692043e962 131
mbed_official 52:27692043e962 132 if (strstr(msg, "t:lights;") == NULL) {
mbed_official 52:27692043e962 133 return;
mbed_official 52:27692043e962 134 }
mbed_official 52:27692043e962 135
mbed_official 52:27692043e962 136 if (strstr(msg, "s:1;") != NULL) {
mbed_official 52:27692043e962 137 state = 1;
mbed_official 52:27692043e962 138 }
mbed_official 52:27692043e962 139 else if (strstr(msg, "s:0;") != NULL) {
mbed_official 52:27692043e962 140 state = 0;
mbed_official 52:27692043e962 141 }
mbed_official 52:27692043e962 142
mbed_official 52:27692043e962 143 // 0==master, 1==default group
mbed_official 52:27692043e962 144 char *msg_ptr = strstr(msg, "g:");
mbed_official 52:27692043e962 145 if (msg_ptr) {
mbed_official 52:27692043e962 146 char *ptr;
mbed_official 52:27692043e962 147 group = strtol(msg_ptr, &ptr, 10);
mbed_official 52:27692043e962 148 }
mbed_official 52:27692043e962 149
mbed_official 52:27692043e962 150 // in this example we only use one group
mbed_official 52:27692043e962 151 if (group==MASTER_GROUP || group==MY_GROUP) {
mbed_official 52:27692043e962 152 update_state(state);
mbed_official 52:27692043e962 153 }
mbed_official 52:27692043e962 154 }
mbed_official 52:27692043e962 155
mbed_official 52:27692043e962 156 static void receive() {
mbed_official 52:27692043e962 157 // Read data from the socket
mbed_official 52:27692043e962 158 SocketAddress source_addr;
mbed_official 52:27692043e962 159 memset(receive_buffer, 0, sizeof(receive_buffer));
mbed_official 52:27692043e962 160 bool something_in_socket=true;
mbed_official 52:27692043e962 161 // read all messages
mbed_official 52:27692043e962 162 while (something_in_socket) {
mbed_official 52:27692043e962 163 int length = my_socket->recvfrom(&source_addr, receive_buffer, sizeof(receive_buffer) - 1);
mbed_official 52:27692043e962 164 if (length > 0) {
mbed_official 52:27692043e962 165 int timeout_value = MESSAGE_WAIT_TIMEOUT;
mbed_official 52:27692043e962 166 tr_debug("Packet from %s\n", source_addr.get_ip_address());
mbed_official 52:27692043e962 167 timeout_value += rand() % 30;
mbed_official 52:27692043e962 168 tr_debug("Advertisiment after %d seconds", timeout_value);
mbed_official 52:27692043e962 169 messageTimeout.detach();
mbed_official 52:27692043e962 170 messageTimeout.attach(&messageTimeoutCallback, timeout_value);
mbed_official 52:27692043e962 171 // Handle command - "on", "off"
mbed_official 52:27692043e962 172 handle_message((char*)receive_buffer);
mbed_official 52:27692043e962 173 }
mbed_official 52:27692043e962 174 else if (length!=NSAPI_ERROR_WOULD_BLOCK) {
mbed_official 52:27692043e962 175 tr_error("Error happened when receiving %d\n", length);
mbed_official 52:27692043e962 176 something_in_socket=false;
mbed_official 52:27692043e962 177 }
mbed_official 52:27692043e962 178 else {
mbed_official 52:27692043e962 179 // there was nothing to read.
mbed_official 52:27692043e962 180 something_in_socket=false;
mbed_official 52:27692043e962 181 }
mbed_official 59:3e1533ffb4f5 182 }
mbed_official 52:27692043e962 183 }
mbed_official 52:27692043e962 184
mbed_official 52:27692043e962 185 static void handle_socket() {
mbed_official 52:27692043e962 186 // call-back might come from ISR
mbed_official 52:27692043e962 187 queue.call(receive);
mbed_official 52:27692043e962 188 }
mbed_official 52:27692043e962 189
mbed_official 52:27692043e962 190 static void init_socket()
mbed_official 52:27692043e962 191 {
mbed_official 52:27692043e962 192 my_socket = new UDPSocket(network_if);
mbed_official 52:27692043e962 193 my_socket->set_blocking(false);
mbed_official 59:3e1533ffb4f5 194 my_socket->bind(UDP_PORT);
mbed_official 52:27692043e962 195 my_socket->setsockopt(SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, &multicast_hops, sizeof(multicast_hops));
mbed_official 59:3e1533ffb4f5 196
mbed_official 59:3e1533ffb4f5 197 ns_ipv6_mreq_t mreq;
mbed_official 59:3e1533ffb4f5 198 memcpy(mreq.ipv6mr_multiaddr, multi_cast_addr, 16);
mbed_official 59:3e1533ffb4f5 199 mreq.ipv6mr_interface = 0;
mbed_official 59:3e1533ffb4f5 200
mbed_official 59:3e1533ffb4f5 201 my_socket->setsockopt(SOCKET_IPPROTO_IPV6, SOCKET_IPV6_JOIN_GROUP, &mreq, sizeof mreq);
mbed_official 59:3e1533ffb4f5 202
mbed_official 52:27692043e962 203 if (MBED_CONF_APP_BUTTON != NC) {
mbed_official 52:27692043e962 204 my_button.fall(&my_button_isr);
mbed_official 52:27692043e962 205 my_button.mode(PullUp);
mbed_official 52:27692043e962 206 }
mbed_official 52:27692043e962 207 //let's register the call-back function.
mbed_official 52:27692043e962 208 //If something happens in socket (packets in or out), the call-back is called.
mbed_official 52:27692043e962 209 my_socket->sigio(callback(handle_socket));
mbed_official 52:27692043e962 210 // dispatch forever
mbed_official 52:27692043e962 211 queue.dispatch();
mbed_official 52:27692043e962 212 }