TCP/IP based digital io controller for operating DigitalsOuts and reading DigitalIns.

Dependencies:   EthernetInterface NetworkAPI mbed-rtos mbed

Fork of NetRelais by Roy van Dam

Committer:
NegativeBlack
Date:
Thu Sep 27 10:00:27 2012 +0000
Revision:
11:e5375ae5c8c3
Parent:
10:22d49341340c
Updated project to latest revision of the NetworkAPI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
NegativeBlack 10:22d49341340c 1 /**
NegativeBlack 10:22d49341340c 2 * Copyright (c) 2012, Roy van Dam <roy@vandam-innovations.com>
NegativeBlack 10:22d49341340c 3 * All rights reserved.
NegativeBlack 10:22d49341340c 4 *
NegativeBlack 10:22d49341340c 5 * Redistribution and use in source and binary forms, with or without
NegativeBlack 10:22d49341340c 6 * modification, are permitted provided that the following conditions are met:
NegativeBlack 10:22d49341340c 7 *
NegativeBlack 10:22d49341340c 8 * 1. Redistributions of source code must retain the above copyright notice, this
NegativeBlack 10:22d49341340c 9 * list of conditions and the following disclaimer.
NegativeBlack 10:22d49341340c 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
NegativeBlack 10:22d49341340c 11 * this list of conditions and the following disclaimer in the documentation
NegativeBlack 10:22d49341340c 12 * and/or other materials provided with the distribution.
NegativeBlack 10:22d49341340c 13 *
NegativeBlack 10:22d49341340c 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
NegativeBlack 10:22d49341340c 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
NegativeBlack 10:22d49341340c 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
NegativeBlack 10:22d49341340c 17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
NegativeBlack 10:22d49341340c 18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
NegativeBlack 10:22d49341340c 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
NegativeBlack 10:22d49341340c 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
NegativeBlack 10:22d49341340c 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
NegativeBlack 10:22d49341340c 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
NegativeBlack 10:22d49341340c 23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
NegativeBlack 10:22d49341340c 24 */
NegativeBlack 10:22d49341340c 25
NegativeBlack 10:22d49341340c 26 #include "controller.hpp"
NegativeBlack 10:22d49341340c 27
NegativeBlack 10:22d49341340c 28 Controller::~Controller()
NegativeBlack 10:22d49341340c 29 {
NegativeBlack 10:22d49341340c 30 this->stop();
NegativeBlack 10:22d49341340c 31 }
NegativeBlack 10:22d49341340c 32
NegativeBlack 10:22d49341340c 33 int
NegativeBlack 10:22d49341340c 34 Controller::start(int port, int max_pending)
NegativeBlack 10:22d49341340c 35 {
NegativeBlack 10:22d49341340c 36 if (this->_network.server.open() < 0) {
NegativeBlack 10:22d49341340c 37 printf("Could not open server socket.\n\r");
NegativeBlack 10:22d49341340c 38 return -1;
NegativeBlack 10:22d49341340c 39 }
NegativeBlack 10:22d49341340c 40
NegativeBlack 10:22d49341340c 41 if (this->_network.server.bind(port) < 0) {
NegativeBlack 10:22d49341340c 42 printf("Could not bind server socket to port '%d'.\n\r", port);
NegativeBlack 10:22d49341340c 43 return -1;
NegativeBlack 10:22d49341340c 44 }
NegativeBlack 10:22d49341340c 45
NegativeBlack 10:22d49341340c 46 if (this->_network.server.listen(max_pending) < 0) {
NegativeBlack 10:22d49341340c 47 printf("Could not put server socket into listening mode.\n\r");
NegativeBlack 10:22d49341340c 48 return -1;
NegativeBlack 10:22d49341340c 49 }
NegativeBlack 10:22d49341340c 50
NegativeBlack 10:22d49341340c 51 return 0;
NegativeBlack 10:22d49341340c 52 }
NegativeBlack 10:22d49341340c 53
NegativeBlack 10:22d49341340c 54 int
NegativeBlack 10:22d49341340c 55 Controller::stop()
NegativeBlack 10:22d49341340c 56 {
NegativeBlack 10:22d49341340c 57 this->_network.server.close();
NegativeBlack 10:22d49341340c 58 this->_network.client.close();
NegativeBlack 11:e5375ae5c8c3 59 return 0;
NegativeBlack 10:22d49341340c 60 }
NegativeBlack 10:22d49341340c 61
NegativeBlack 10:22d49341340c 62 int
NegativeBlack 10:22d49341340c 63 Controller::dispatch()
NegativeBlack 10:22d49341340c 64 {
NegativeBlack 10:22d49341340c 65 int result = 0;
NegativeBlack 10:22d49341340c 66 network::Buffer buffer(256);
NegativeBlack 10:22d49341340c 67
NegativeBlack 10:22d49341340c 68 while (this->_network.server.getStatus() == network::Socket::Listening) {
NegativeBlack 10:22d49341340c 69 if (this->_network.server.accept(this->_network.client) < 0) {
NegativeBlack 10:22d49341340c 70 printf("Warning: failed to accept connection.\n\r");
NegativeBlack 10:22d49341340c 71 continue;
NegativeBlack 10:22d49341340c 72 }
NegativeBlack 10:22d49341340c 73
NegativeBlack 10:22d49341340c 74 printf("Client connected '%s:%d'.\n\r",
NegativeBlack 10:22d49341340c 75 this->_network.client.getRemoteEndpoint().getAddress().toString().c_str(),
NegativeBlack 10:22d49341340c 76 this->_network.client.getRemoteEndpoint().getPort());
NegativeBlack 10:22d49341340c 77
NegativeBlack 10:22d49341340c 78 while (this->_network.client.getStatus() == network::Socket::Connected) {
NegativeBlack 10:22d49341340c 79 buffer.flush();
NegativeBlack 10:22d49341340c 80
NegativeBlack 10:22d49341340c 81 switch (this->_network.client.read(buffer)) {
NegativeBlack 10:22d49341340c 82 case -1:
NegativeBlack 10:22d49341340c 83 printf("Warning: failed to read data from client.\n\r");
NegativeBlack 10:22d49341340c 84 break;
NegativeBlack 10:22d49341340c 85
NegativeBlack 10:22d49341340c 86 case 0:
NegativeBlack 10:22d49341340c 87 printf("Connection closed.\n\r");
NegativeBlack 10:22d49341340c 88 break;
NegativeBlack 10:22d49341340c 89
NegativeBlack 10:22d49341340c 90 default:
NegativeBlack 11:e5375ae5c8c3 91 printf("Received %d bytes.\n\r%s\r", buffer.length(), (char *)buffer.data());
NegativeBlack 10:22d49341340c 92
NegativeBlack 10:22d49341340c 93 // Parse command
NegativeBlack 10:22d49341340c 94 result = this->_parseCommand(buffer);
NegativeBlack 10:22d49341340c 95
NegativeBlack 10:22d49341340c 96 // Format reply code
NegativeBlack 10:22d49341340c 97 buffer.flush();
NegativeBlack 11:e5375ae5c8c3 98 buffer.length(std::snprintf(
NegativeBlack 11:e5375ae5c8c3 99 (char *)buffer.data(), buffer.size(),
NegativeBlack 10:22d49341340c 100 "e;%i;", result));
NegativeBlack 10:22d49341340c 101
NegativeBlack 10:22d49341340c 102 if (buffer.length() < 4) {
NegativeBlack 10:22d49341340c 103 printf("Warning: failed to format error reply.\n\r");
NegativeBlack 10:22d49341340c 104 continue;
NegativeBlack 10:22d49341340c 105 }
NegativeBlack 10:22d49341340c 106
NegativeBlack 10:22d49341340c 107 if (this->_network.client.write(buffer) < 0) {
NegativeBlack 10:22d49341340c 108 printf("Warning: failed to reply.\n\r");
NegativeBlack 10:22d49341340c 109 }
NegativeBlack 10:22d49341340c 110 continue;
NegativeBlack 10:22d49341340c 111 }
NegativeBlack 10:22d49341340c 112
NegativeBlack 10:22d49341340c 113 this->_network.client.shutdown();
NegativeBlack 10:22d49341340c 114 this->_network.client.close();
NegativeBlack 10:22d49341340c 115 }
NegativeBlack 11:e5375ae5c8c3 116 }
NegativeBlack 11:e5375ae5c8c3 117
NegativeBlack 11:e5375ae5c8c3 118 return 0;
NegativeBlack 10:22d49341340c 119 }
NegativeBlack 10:22d49341340c 120
NegativeBlack 10:22d49341340c 121 int
NegativeBlack 10:22d49341340c 122 Controller::_parseCommand(network::Buffer &buffer)
NegativeBlack 10:22d49341340c 123 {
NegativeBlack 10:22d49341340c 124 int index = 0;
NegativeBlack 10:22d49341340c 125 network::Buffer response(32);
NegativeBlack 11:e5375ae5c8c3 126 char *cursor = (char *)buffer.data();
NegativeBlack 10:22d49341340c 127
NegativeBlack 10:22d49341340c 128 enum Controller::ParseState state = Controller::S_Init;
NegativeBlack 10:22d49341340c 129 enum Controller::Command command = Controller::C_None;
NegativeBlack 10:22d49341340c 130
NegativeBlack 10:22d49341340c 131 while (cursor != NULL) {
NegativeBlack 10:22d49341340c 132 switch (state) {
NegativeBlack 10:22d49341340c 133 case Controller::S_Init: {
NegativeBlack 11:e5375ae5c8c3 134 if (((*cursor) == 'r') && ((*(cursor + 1)) == ':')) {
NegativeBlack 10:22d49341340c 135 command = Controller::C_Read;
NegativeBlack 10:22d49341340c 136 state = Controller::S_Index;
NegativeBlack 10:22d49341340c 137 cursor += 2;
NegativeBlack 10:22d49341340c 138 continue;
NegativeBlack 10:22d49341340c 139 }
NegativeBlack 10:22d49341340c 140
NegativeBlack 11:e5375ae5c8c3 141 if (((*cursor) == 'w') && ((*(cursor + 1)) == ':')) {
NegativeBlack 10:22d49341340c 142 command = Controller::C_Write;
NegativeBlack 10:22d49341340c 143 state = Controller::S_Index;
NegativeBlack 10:22d49341340c 144 cursor += 2;
NegativeBlack 10:22d49341340c 145 continue;
NegativeBlack 10:22d49341340c 146 }
NegativeBlack 10:22d49341340c 147
NegativeBlack 10:22d49341340c 148 return Controller::E_InvalidCommand;
NegativeBlack 10:22d49341340c 149 }
NegativeBlack 10:22d49341340c 150
NegativeBlack 10:22d49341340c 151 case Controller::S_Index: {
NegativeBlack 10:22d49341340c 152 if (std::sscanf(cursor, "%d;", &index) != 1) {
NegativeBlack 10:22d49341340c 153 return Controller::E_InvalidFormat;
NegativeBlack 10:22d49341340c 154 }
NegativeBlack 10:22d49341340c 155
NegativeBlack 11:e5375ae5c8c3 156 char *offset;
NegativeBlack 11:e5375ae5c8c3 157 switch (command) {
NegativeBlack 11:e5375ae5c8c3 158 case Controller::C_Read: {
NegativeBlack 11:e5375ae5c8c3 159 offset = std::strchr(cursor, ';');
NegativeBlack 11:e5375ae5c8c3 160 break;
NegativeBlack 11:e5375ae5c8c3 161 }
NegativeBlack 11:e5375ae5c8c3 162
NegativeBlack 11:e5375ae5c8c3 163 case Controller::C_Write: {
NegativeBlack 11:e5375ae5c8c3 164 offset = std::strchr(cursor, ':');
NegativeBlack 11:e5375ae5c8c3 165 break;
NegativeBlack 11:e5375ae5c8c3 166 }
NegativeBlack 11:e5375ae5c8c3 167 }
NegativeBlack 11:e5375ae5c8c3 168
NegativeBlack 10:22d49341340c 169 if (offset == NULL) {
NegativeBlack 10:22d49341340c 170 return Controller::E_InvalidFormat;
NegativeBlack 10:22d49341340c 171 }
NegativeBlack 10:22d49341340c 172
NegativeBlack 10:22d49341340c 173 cursor = offset + 1;
NegativeBlack 10:22d49341340c 174 state = Controller::S_Execute;
NegativeBlack 10:22d49341340c 175 continue;
NegativeBlack 10:22d49341340c 176 }
NegativeBlack 10:22d49341340c 177
NegativeBlack 10:22d49341340c 178 case Controller::S_Execute: {
NegativeBlack 10:22d49341340c 179 switch (command) {
NegativeBlack 10:22d49341340c 180 case Controller::C_Read: {
NegativeBlack 10:22d49341340c 181 DigitalIn *input = this->getInput(index);
NegativeBlack 10:22d49341340c 182 if (input == NULL) {
NegativeBlack 10:22d49341340c 183 return Controller::E_UnknownIndex;
NegativeBlack 10:22d49341340c 184 }
NegativeBlack 10:22d49341340c 185
NegativeBlack 11:e5375ae5c8c3 186 response.length(std::snprintf(
NegativeBlack 11:e5375ae5c8c3 187 (char *)response.data(), response.size(),
NegativeBlack 11:e5375ae5c8c3 188 "r:%d:%d;", index, input->read()));
NegativeBlack 10:22d49341340c 189
NegativeBlack 10:22d49341340c 190 if (response.length() < 6) {
NegativeBlack 10:22d49341340c 191 printf("Warning: failed to format reply.\n\r");
NegativeBlack 10:22d49341340c 192 return Controller::E_Internal;
NegativeBlack 10:22d49341340c 193 }
NegativeBlack 10:22d49341340c 194
NegativeBlack 10:22d49341340c 195 if (this->_network.client.write(response) < 0) {
NegativeBlack 10:22d49341340c 196 printf("Warning: failed to reply on read request.\n\r");
NegativeBlack 10:22d49341340c 197 return Controller::E_Internal;
NegativeBlack 10:22d49341340c 198 }
NegativeBlack 10:22d49341340c 199
NegativeBlack 10:22d49341340c 200 if ((*cursor) == 0 || (*(cursor + 1)) == 0) {
NegativeBlack 10:22d49341340c 201 return 0;
NegativeBlack 10:22d49341340c 202 }
NegativeBlack 10:22d49341340c 203
NegativeBlack 10:22d49341340c 204 command = Controller::C_None;
NegativeBlack 10:22d49341340c 205 state = Controller::S_Init;
NegativeBlack 10:22d49341340c 206 continue;
NegativeBlack 10:22d49341340c 207 }
NegativeBlack 10:22d49341340c 208
NegativeBlack 10:22d49341340c 209 case Controller::C_Write: {
NegativeBlack 10:22d49341340c 210 DigitalOut *output = this->getOutput(index);
NegativeBlack 10:22d49341340c 211 if (output == NULL) {
NegativeBlack 10:22d49341340c 212 return Controller::E_UnknownIndex;
NegativeBlack 10:22d49341340c 213 }
NegativeBlack 10:22d49341340c 214
NegativeBlack 10:22d49341340c 215 int value = 0;
NegativeBlack 10:22d49341340c 216 if (std::sscanf(cursor, "%d;", &value) != 1) {
NegativeBlack 10:22d49341340c 217 return Controller::E_InvalidFormat;
NegativeBlack 10:22d49341340c 218 }
NegativeBlack 10:22d49341340c 219
NegativeBlack 10:22d49341340c 220 char *offset = std::strchr(cursor, ';');
NegativeBlack 10:22d49341340c 221 if (offset == NULL) {
NegativeBlack 10:22d49341340c 222 return Controller::E_InvalidFormat;
NegativeBlack 10:22d49341340c 223 }
NegativeBlack 10:22d49341340c 224 cursor = offset + 1;
NegativeBlack 10:22d49341340c 225
NegativeBlack 10:22d49341340c 226 if (value != 0 && value != 1) {
NegativeBlack 10:22d49341340c 227 return Controller::E_InvalidValue;
NegativeBlack 10:22d49341340c 228 }
NegativeBlack 10:22d49341340c 229
NegativeBlack 10:22d49341340c 230 output->write(value);
NegativeBlack 10:22d49341340c 231
NegativeBlack 10:22d49341340c 232 if ((*cursor) == 0 || (*(cursor + 1)) == 0) {
NegativeBlack 10:22d49341340c 233 return 0;
NegativeBlack 10:22d49341340c 234 }
NegativeBlack 10:22d49341340c 235
NegativeBlack 10:22d49341340c 236 command = Controller::C_None;
NegativeBlack 10:22d49341340c 237 state = Controller::S_Init;
NegativeBlack 10:22d49341340c 238 continue;
NegativeBlack 10:22d49341340c 239 }
NegativeBlack 10:22d49341340c 240 }
NegativeBlack 10:22d49341340c 241 }
NegativeBlack 10:22d49341340c 242 }
NegativeBlack 10:22d49341340c 243 }
NegativeBlack 10:22d49341340c 244
NegativeBlack 10:22d49341340c 245 return 0;
NegativeBlack 10:22d49341340c 246 }
NegativeBlack 10:22d49341340c 247
NegativeBlack 10:22d49341340c 248
NegativeBlack 10:22d49341340c 249 int
NegativeBlack 10:22d49341340c 250 Controller::addOutput(DigitalOut *output)
NegativeBlack 10:22d49341340c 251 {
NegativeBlack 10:22d49341340c 252 if (this->_outputExists(output)) {
NegativeBlack 10:22d49341340c 253 return false;
NegativeBlack 10:22d49341340c 254 }
NegativeBlack 10:22d49341340c 255
NegativeBlack 10:22d49341340c 256 this->_io.output.push_back(output);
NegativeBlack 10:22d49341340c 257 return true;
NegativeBlack 10:22d49341340c 258 }
NegativeBlack 10:22d49341340c 259
NegativeBlack 10:22d49341340c 260 int
NegativeBlack 10:22d49341340c 261 Controller::addInput(DigitalIn *input)
NegativeBlack 10:22d49341340c 262 {
NegativeBlack 10:22d49341340c 263 if (this->_inputExists(input)) {
NegativeBlack 10:22d49341340c 264 return false;
NegativeBlack 10:22d49341340c 265 }
NegativeBlack 10:22d49341340c 266
NegativeBlack 10:22d49341340c 267 this->_io.input.push_back(input);
NegativeBlack 10:22d49341340c 268 return true;
NegativeBlack 10:22d49341340c 269 }
NegativeBlack 10:22d49341340c 270
NegativeBlack 10:22d49341340c 271 DigitalOut *
NegativeBlack 10:22d49341340c 272 Controller::getOutput(size_t index)
NegativeBlack 10:22d49341340c 273 {
NegativeBlack 10:22d49341340c 274 Controller::DigitalOutputList::iterator output;
NegativeBlack 10:22d49341340c 275 output = this->_io.output.begin();
NegativeBlack 10:22d49341340c 276 output = output + (int)index;
NegativeBlack 10:22d49341340c 277
NegativeBlack 10:22d49341340c 278 if (output >= this->_io.output.end()) {
NegativeBlack 10:22d49341340c 279 return NULL;
NegativeBlack 10:22d49341340c 280 }
NegativeBlack 10:22d49341340c 281
NegativeBlack 10:22d49341340c 282 return (*output);
NegativeBlack 10:22d49341340c 283 }
NegativeBlack 10:22d49341340c 284
NegativeBlack 10:22d49341340c 285 DigitalIn *
NegativeBlack 10:22d49341340c 286 Controller::getInput(size_t index)
NegativeBlack 10:22d49341340c 287 {
NegativeBlack 10:22d49341340c 288 DigitalInputList::iterator input;
NegativeBlack 10:22d49341340c 289 input = this->_io.input.begin();
NegativeBlack 10:22d49341340c 290 input = input + (int)index;
NegativeBlack 10:22d49341340c 291
NegativeBlack 10:22d49341340c 292 if (input >= this->_io.input.end()) {
NegativeBlack 10:22d49341340c 293 return NULL;
NegativeBlack 10:22d49341340c 294 }
NegativeBlack 10:22d49341340c 295
NegativeBlack 10:22d49341340c 296 return (*input);
NegativeBlack 10:22d49341340c 297 }
NegativeBlack 10:22d49341340c 298
NegativeBlack 10:22d49341340c 299 bool
NegativeBlack 10:22d49341340c 300 Controller::_outputExists(DigitalOut *output)
NegativeBlack 10:22d49341340c 301 {
NegativeBlack 10:22d49341340c 302 DigitalOutputList::iterator entry;
NegativeBlack 10:22d49341340c 303 entry = this->_io.output.begin();
NegativeBlack 10:22d49341340c 304 for (;entry != this->_io.output.end(); entry++) {
NegativeBlack 10:22d49341340c 305 if (output == (*entry)) {
NegativeBlack 10:22d49341340c 306 return true;
NegativeBlack 10:22d49341340c 307 }
NegativeBlack 10:22d49341340c 308 }
NegativeBlack 10:22d49341340c 309
NegativeBlack 10:22d49341340c 310 return false;
NegativeBlack 10:22d49341340c 311 }
NegativeBlack 10:22d49341340c 312
NegativeBlack 10:22d49341340c 313 bool
NegativeBlack 10:22d49341340c 314 Controller::_inputExists(DigitalIn *input)
NegativeBlack 10:22d49341340c 315 {
NegativeBlack 10:22d49341340c 316 Controller::DigitalInputList::iterator entry;
NegativeBlack 10:22d49341340c 317 entry = this->_io.input.begin();
NegativeBlack 10:22d49341340c 318 for (;entry != this->_io.input.end(); entry++) {
NegativeBlack 10:22d49341340c 319 if (input == (*entry)) {
NegativeBlack 10:22d49341340c 320 return true;
NegativeBlack 10:22d49341340c 321 }
NegativeBlack 10:22d49341340c 322 }
NegativeBlack 10:22d49341340c 323
NegativeBlack 10:22d49341340c 324 return false;
NegativeBlack 10:22d49341340c 325 }