Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
mesh_led_control_example.cpp@116:b2f0131722a0, 2018-12-20 (annotated)
- Committer:
- mbed_official
- Date:
- Thu Dec 20 14:30:49 2018 +0000
- Revision:
- 116:b2f0131722a0
- Parent:
- 90:0d8804fe2ce2
Merge pull request #235 from ARMmbed/mbed-os-5.11.0-oob
Mbed OS 5.11.0
.
Commit copied from https://github.com/ARMmbed/mbed-os-example-mesh-minimal
Who changed what in which revision?
| User | Revision | Line number | New 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 | |
| mbed_official | 52:27692043e962 | 43 | NetworkInterface * network_if; | 
| mbed_official | 52:27692043e962 | 44 | UDPSocket* my_socket; | 
| mbed_official | 52:27692043e962 | 45 | // queue for sending messages from button press. | 
| mbed_official | 52:27692043e962 | 46 | EventQueue queue; | 
| mbed_official | 52:27692043e962 | 47 | // for LED blinking | 
| mbed_official | 52:27692043e962 | 48 | Ticker ticker; | 
| mbed_official | 66:30f2c1317e6d | 49 | // Handle for delayed message send | 
| mbed_official | 66:30f2c1317e6d | 50 | int queue_handle = 0; | 
| mbed_official | 52:27692043e962 | 51 | |
| mbed_official | 52:27692043e962 | 52 | uint8_t multi_cast_addr[16] = {0}; | 
| mbed_official | 52:27692043e962 | 53 | uint8_t receive_buffer[20]; | 
| mbed_official | 52:27692043e962 | 54 | // how many hops the multicast message can go | 
| mbed_official | 52:27692043e962 | 55 | static const int16_t multicast_hops = 10; | 
| mbed_official | 52:27692043e962 | 56 | bool button_status = 0; | 
| mbed_official | 52:27692043e962 | 57 | |
| mbed_official | 52:27692043e962 | 58 | void start_mesh_led_control_example(NetworkInterface * interface){ | 
| mbed_official | 52:27692043e962 | 59 | tr_debug("start_mesh_led_control_example()"); | 
| mbed_official | 52:27692043e962 | 60 | MBED_ASSERT(MBED_CONF_APP_LED != NC); | 
| mbed_official | 52:27692043e962 | 61 | MBED_ASSERT(MBED_CONF_APP_BUTTON != NC); | 
| mbed_official | 52:27692043e962 | 62 | |
| mbed_official | 52:27692043e962 | 63 | network_if = interface; | 
| mbed_official | 52:27692043e962 | 64 | stoip6(multicast_addr_str, strlen(multicast_addr_str), multi_cast_addr); | 
| mbed_official | 52:27692043e962 | 65 | init_socket(); | 
| mbed_official | 52:27692043e962 | 66 | } | 
| mbed_official | 52:27692043e962 | 67 | |
| mbed_official | 52:27692043e962 | 68 | static void blink() { | 
| mbed_official | 52:27692043e962 | 69 | led_1 = !led_1; | 
| mbed_official | 52:27692043e962 | 70 | } | 
| mbed_official | 52:27692043e962 | 71 | |
| mbed_official | 52:27692043e962 | 72 | void start_blinking() { | 
| mbed_official | 52:27692043e962 | 73 | ticker.attach(blink, 1.0); | 
| mbed_official | 52:27692043e962 | 74 | } | 
| mbed_official | 52:27692043e962 | 75 | |
| mbed_official | 52:27692043e962 | 76 | void cancel_blinking() { | 
| mbed_official | 52:27692043e962 | 77 | ticker.detach(); | 
| mbed_official | 52:27692043e962 | 78 | led_1=1; | 
| mbed_official | 52:27692043e962 | 79 | } | 
| mbed_official | 52:27692043e962 | 80 | |
| mbed_official | 52:27692043e962 | 81 | static void send_message() { | 
| mbed_official | 52:27692043e962 | 82 | tr_debug("send msg %d", button_status); | 
| mbed_official | 52:27692043e962 | 83 | |
| mbed_official | 52:27692043e962 | 84 | char buf[20]; | 
| mbed_official | 52:27692043e962 | 85 | int length; | 
| mbed_official | 52:27692043e962 | 86 | |
| mbed_official | 52:27692043e962 | 87 | /** | 
| mbed_official | 52:27692043e962 | 88 | * Multicast control message is a NUL terminated string of semicolon separated | 
| mbed_official | 52:27692043e962 | 89 | * <field identifier>:<value> pairs. | 
| mbed_official | 52:27692043e962 | 90 | * | 
| mbed_official | 52:27692043e962 | 91 | * Light control message format: | 
| mbed_official | 52:27692043e962 | 92 | * t:lights;g:<group_id>;s:<1|0>;\0 | 
| mbed_official | 52:27692043e962 | 93 | */ | 
| mbed_official | 52:27692043e962 | 94 | length = snprintf(buf, sizeof(buf), "t:lights;g:%03d;s:%s;", MY_GROUP, (button_status ? "1" : "0")) + 1; | 
| mbed_official | 52:27692043e962 | 95 | MBED_ASSERT(length > 0); | 
| mbed_official | 52:27692043e962 | 96 | tr_debug("Sending lightcontrol message, %d bytes: %s", length, buf); | 
| mbed_official | 52:27692043e962 | 97 | SocketAddress send_sockAddr(multi_cast_addr, NSAPI_IPv6, UDP_PORT); | 
| mbed_official | 52:27692043e962 | 98 | my_socket->sendto(send_sockAddr, buf, 20); | 
| mbed_official | 52:27692043e962 | 99 | //After message is sent, it is received from the network | 
| mbed_official | 52:27692043e962 | 100 | } | 
| mbed_official | 52:27692043e962 | 101 | |
| mbed_official | 52:27692043e962 | 102 | // As this comes from isr, we cannot use printing or network functions directly from here. | 
| mbed_official | 52:27692043e962 | 103 | static void my_button_isr() { | 
| mbed_official | 52:27692043e962 | 104 | button_status = !button_status; | 
| mbed_official | 52:27692043e962 | 105 | queue.call(send_message); | 
| mbed_official | 52:27692043e962 | 106 | } | 
| mbed_official | 52:27692043e962 | 107 | |
| mbed_official | 52:27692043e962 | 108 | static void update_state(uint8_t state) { | 
| mbed_official | 52:27692043e962 | 109 | if (state == 1) { | 
| mbed_official | 52:27692043e962 | 110 | tr_debug("Turning led on\n"); | 
| mbed_official | 52:27692043e962 | 111 | led_1 = 0; | 
| mbed_official | 52:27692043e962 | 112 | button_status=1; | 
| mbed_official | 52:27692043e962 | 113 | output = 0; | 
| mbed_official | 52:27692043e962 | 114 | } | 
| mbed_official | 52:27692043e962 | 115 | else { | 
| mbed_official | 52:27692043e962 | 116 | tr_debug("Turning led off\n"); | 
| mbed_official | 52:27692043e962 | 117 | led_1 = 1; | 
| mbed_official | 52:27692043e962 | 118 | button_status=0; | 
| mbed_official | 52:27692043e962 | 119 | output = 1; | 
| mbed_official | 52:27692043e962 | 120 | } | 
| mbed_official | 52:27692043e962 | 121 | } | 
| mbed_official | 52:27692043e962 | 122 | |
| mbed_official | 52:27692043e962 | 123 | static void handle_message(char* msg) { | 
| mbed_official | 52:27692043e962 | 124 | // Check if this is lights message | 
| mbed_official | 52:27692043e962 | 125 | uint8_t state=button_status; | 
| mbed_official | 52:27692043e962 | 126 | uint16_t group=0xffff; | 
| mbed_official | 52:27692043e962 | 127 | |
| mbed_official | 52:27692043e962 | 128 | if (strstr(msg, "t:lights;") == NULL) { | 
| mbed_official | 52:27692043e962 | 129 | return; | 
| mbed_official | 52:27692043e962 | 130 | } | 
| mbed_official | 52:27692043e962 | 131 | |
| mbed_official | 52:27692043e962 | 132 | if (strstr(msg, "s:1;") != NULL) { | 
| mbed_official | 52:27692043e962 | 133 | state = 1; | 
| mbed_official | 52:27692043e962 | 134 | } | 
| mbed_official | 52:27692043e962 | 135 | else if (strstr(msg, "s:0;") != NULL) { | 
| mbed_official | 52:27692043e962 | 136 | state = 0; | 
| mbed_official | 52:27692043e962 | 137 | } | 
| mbed_official | 52:27692043e962 | 138 | |
| mbed_official | 52:27692043e962 | 139 | // 0==master, 1==default group | 
| mbed_official | 52:27692043e962 | 140 | char *msg_ptr = strstr(msg, "g:"); | 
| mbed_official | 52:27692043e962 | 141 | if (msg_ptr) { | 
| mbed_official | 52:27692043e962 | 142 | char *ptr; | 
| mbed_official | 52:27692043e962 | 143 | group = strtol(msg_ptr, &ptr, 10); | 
| mbed_official | 52:27692043e962 | 144 | } | 
| mbed_official | 52:27692043e962 | 145 | |
| mbed_official | 52:27692043e962 | 146 | // in this example we only use one group | 
| mbed_official | 52:27692043e962 | 147 | if (group==MASTER_GROUP || group==MY_GROUP) { | 
| mbed_official | 52:27692043e962 | 148 | update_state(state); | 
| mbed_official | 52:27692043e962 | 149 | } | 
| mbed_official | 52:27692043e962 | 150 | } | 
| mbed_official | 52:27692043e962 | 151 | |
| mbed_official | 52:27692043e962 | 152 | static void receive() { | 
| mbed_official | 52:27692043e962 | 153 | // Read data from the socket | 
| mbed_official | 52:27692043e962 | 154 | SocketAddress source_addr; | 
| mbed_official | 52:27692043e962 | 155 | memset(receive_buffer, 0, sizeof(receive_buffer)); | 
| mbed_official | 52:27692043e962 | 156 | bool something_in_socket=true; | 
| mbed_official | 52:27692043e962 | 157 | // read all messages | 
| mbed_official | 52:27692043e962 | 158 | while (something_in_socket) { | 
| mbed_official | 52:27692043e962 | 159 | int length = my_socket->recvfrom(&source_addr, receive_buffer, sizeof(receive_buffer) - 1); | 
| mbed_official | 52:27692043e962 | 160 | if (length > 0) { | 
| mbed_official | 52:27692043e962 | 161 | int timeout_value = MESSAGE_WAIT_TIMEOUT; | 
| mbed_official | 52:27692043e962 | 162 | tr_debug("Packet from %s\n", source_addr.get_ip_address()); | 
| mbed_official | 52:27692043e962 | 163 | timeout_value += rand() % 30; | 
| mbed_official | 52:27692043e962 | 164 | tr_debug("Advertisiment after %d seconds", timeout_value); | 
| mbed_official | 66:30f2c1317e6d | 165 | queue.cancel(queue_handle); | 
| mbed_official | 66:30f2c1317e6d | 166 | queue_handle = queue.call_in((timeout_value * 1000), send_message); | 
| mbed_official | 52:27692043e962 | 167 | // Handle command - "on", "off" | 
| mbed_official | 52:27692043e962 | 168 | handle_message((char*)receive_buffer); | 
| mbed_official | 52:27692043e962 | 169 | } | 
| mbed_official | 52:27692043e962 | 170 | else if (length!=NSAPI_ERROR_WOULD_BLOCK) { | 
| mbed_official | 52:27692043e962 | 171 | tr_error("Error happened when receiving %d\n", length); | 
| mbed_official | 52:27692043e962 | 172 | something_in_socket=false; | 
| mbed_official | 52:27692043e962 | 173 | } | 
| mbed_official | 52:27692043e962 | 174 | else { | 
| mbed_official | 52:27692043e962 | 175 | // there was nothing to read. | 
| mbed_official | 52:27692043e962 | 176 | something_in_socket=false; | 
| mbed_official | 52:27692043e962 | 177 | } | 
| mbed_official | 59:3e1533ffb4f5 | 178 | } | 
| mbed_official | 52:27692043e962 | 179 | } | 
| mbed_official | 52:27692043e962 | 180 | |
| mbed_official | 52:27692043e962 | 181 | static void handle_socket() { | 
| mbed_official | 52:27692043e962 | 182 | // call-back might come from ISR | 
| mbed_official | 52:27692043e962 | 183 | queue.call(receive); | 
| mbed_official | 52:27692043e962 | 184 | } | 
| mbed_official | 52:27692043e962 | 185 | |
| mbed_official | 52:27692043e962 | 186 | static void init_socket() | 
| mbed_official | 52:27692043e962 | 187 | { | 
| mbed_official | 116:b2f0131722a0 | 188 | my_socket = new UDPSocket(); | 
| mbed_official | 116:b2f0131722a0 | 189 | my_socket->open(network_if); | 
| mbed_official | 52:27692043e962 | 190 | my_socket->set_blocking(false); | 
| mbed_official | 59:3e1533ffb4f5 | 191 | my_socket->bind(UDP_PORT); | 
| mbed_official | 52:27692043e962 | 192 | my_socket->setsockopt(SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, &multicast_hops, sizeof(multicast_hops)); | 
| mbed_official | 59:3e1533ffb4f5 | 193 | |
| mbed_official | 59:3e1533ffb4f5 | 194 | ns_ipv6_mreq_t mreq; | 
| mbed_official | 59:3e1533ffb4f5 | 195 | memcpy(mreq.ipv6mr_multiaddr, multi_cast_addr, 16); | 
| mbed_official | 59:3e1533ffb4f5 | 196 | mreq.ipv6mr_interface = 0; | 
| mbed_official | 59:3e1533ffb4f5 | 197 | |
| mbed_official | 59:3e1533ffb4f5 | 198 | my_socket->setsockopt(SOCKET_IPPROTO_IPV6, SOCKET_IPV6_JOIN_GROUP, &mreq, sizeof mreq); | 
| mbed_official | 59:3e1533ffb4f5 | 199 | |
| mbed_official | 52:27692043e962 | 200 | if (MBED_CONF_APP_BUTTON != NC) { | 
| mbed_official | 52:27692043e962 | 201 | my_button.fall(&my_button_isr); | 
| mbed_official | 90:0d8804fe2ce2 | 202 | my_button.mode(MBED_CONF_APP_BUTTON_MODE); | 
| mbed_official | 52:27692043e962 | 203 | } | 
| mbed_official | 52:27692043e962 | 204 | //let's register the call-back function. | 
| mbed_official | 52:27692043e962 | 205 | //If something happens in socket (packets in or out), the call-back is called. | 
| mbed_official | 52:27692043e962 | 206 | my_socket->sigio(callback(handle_socket)); | 
| mbed_official | 52:27692043e962 | 207 | // dispatch forever | 
| mbed_official | 52:27692043e962 | 208 | queue.dispatch(); | 
| mbed_official | 52:27692043e962 | 209 | } |