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 Jul 19 11:13:50 2012 +0000
Revision:
10:22d49341340c
Child:
11:e5375ae5c8c3
Implemented TCP/IP based digital io interface.

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 10:22d49341340c 59 }
NegativeBlack 10:22d49341340c 60
NegativeBlack 10:22d49341340c 61 int
NegativeBlack 10:22d49341340c 62 Controller::dispatch()
NegativeBlack 10:22d49341340c 63 {
NegativeBlack 10:22d49341340c 64 int result = 0;
NegativeBlack 10:22d49341340c 65 network::Buffer buffer(256);
NegativeBlack 10:22d49341340c 66
NegativeBlack 10:22d49341340c 67 while (this->_network.server.getStatus() == network::Socket::Listening) {
NegativeBlack 10:22d49341340c 68 if (this->_network.server.accept(this->_network.client) < 0) {
NegativeBlack 10:22d49341340c 69 printf("Warning: failed to accept connection.\n\r");
NegativeBlack 10:22d49341340c 70 continue;
NegativeBlack 10:22d49341340c 71 }
NegativeBlack 10:22d49341340c 72
NegativeBlack 10:22d49341340c 73 printf("Client connected '%s:%d'.\n\r",
NegativeBlack 10:22d49341340c 74 this->_network.client.getRemoteEndpoint().getAddress().toString().c_str(),
NegativeBlack 10:22d49341340c 75 this->_network.client.getRemoteEndpoint().getPort());
NegativeBlack 10:22d49341340c 76
NegativeBlack 10:22d49341340c 77 while (this->_network.client.getStatus() == network::Socket::Connected) {
NegativeBlack 10:22d49341340c 78 buffer.flush();
NegativeBlack 10:22d49341340c 79
NegativeBlack 10:22d49341340c 80 switch (this->_network.client.read(buffer)) {
NegativeBlack 10:22d49341340c 81 case -1:
NegativeBlack 10:22d49341340c 82 printf("Warning: failed to read data from client.\n\r");
NegativeBlack 10:22d49341340c 83 break;
NegativeBlack 10:22d49341340c 84
NegativeBlack 10:22d49341340c 85 case 0:
NegativeBlack 10:22d49341340c 86 printf("Connection closed.\n\r");
NegativeBlack 10:22d49341340c 87 break;
NegativeBlack 10:22d49341340c 88
NegativeBlack 10:22d49341340c 89 default:
NegativeBlack 10:22d49341340c 90 printf("Received %d bytes.\n\r%s\r", buffer.length(), (char *)buffer.pointer());
NegativeBlack 10:22d49341340c 91
NegativeBlack 10:22d49341340c 92 // Parse command
NegativeBlack 10:22d49341340c 93 result = this->_parseCommand(buffer);
NegativeBlack 10:22d49341340c 94
NegativeBlack 10:22d49341340c 95 // Format reply code
NegativeBlack 10:22d49341340c 96 buffer.flush();
NegativeBlack 10:22d49341340c 97 buffer.setLength(std::snprintf(
NegativeBlack 10:22d49341340c 98 (char *)buffer.pointer(), buffer.size(),
NegativeBlack 10:22d49341340c 99 "e;%i;", result));
NegativeBlack 10:22d49341340c 100
NegativeBlack 10:22d49341340c 101 if (buffer.length() < 4) {
NegativeBlack 10:22d49341340c 102 printf("Warning: failed to format error reply.\n\r");
NegativeBlack 10:22d49341340c 103 continue;
NegativeBlack 10:22d49341340c 104 }
NegativeBlack 10:22d49341340c 105
NegativeBlack 10:22d49341340c 106 if (this->_network.client.write(buffer) < 0) {
NegativeBlack 10:22d49341340c 107 printf("Warning: failed to reply.\n\r");
NegativeBlack 10:22d49341340c 108 }
NegativeBlack 10:22d49341340c 109 continue;
NegativeBlack 10:22d49341340c 110 }
NegativeBlack 10:22d49341340c 111
NegativeBlack 10:22d49341340c 112 this->_network.client.shutdown();
NegativeBlack 10:22d49341340c 113 this->_network.client.close();
NegativeBlack 10:22d49341340c 114 }
NegativeBlack 10:22d49341340c 115 }
NegativeBlack 10:22d49341340c 116 }
NegativeBlack 10:22d49341340c 117
NegativeBlack 10:22d49341340c 118 int
NegativeBlack 10:22d49341340c 119 Controller::_parseCommand(network::Buffer &buffer)
NegativeBlack 10:22d49341340c 120 {
NegativeBlack 10:22d49341340c 121 int index = 0;
NegativeBlack 10:22d49341340c 122 network::Buffer response(32);
NegativeBlack 10:22d49341340c 123 char *cursor = (char *)buffer.pointer();
NegativeBlack 10:22d49341340c 124
NegativeBlack 10:22d49341340c 125 enum Controller::ParseState state = Controller::S_Init;
NegativeBlack 10:22d49341340c 126 enum Controller::Command command = Controller::C_None;
NegativeBlack 10:22d49341340c 127
NegativeBlack 10:22d49341340c 128 while (cursor != NULL) {
NegativeBlack 10:22d49341340c 129 switch (state) {
NegativeBlack 10:22d49341340c 130 case Controller::S_Init: {
NegativeBlack 10:22d49341340c 131 if (((*cursor) == 'r') && ((*(cursor + 1)) == ';')) {
NegativeBlack 10:22d49341340c 132 command = Controller::C_Read;
NegativeBlack 10:22d49341340c 133 state = Controller::S_Index;
NegativeBlack 10:22d49341340c 134 cursor += 2;
NegativeBlack 10:22d49341340c 135 continue;
NegativeBlack 10:22d49341340c 136 }
NegativeBlack 10:22d49341340c 137
NegativeBlack 10:22d49341340c 138 if (((*cursor) == 'w') && ((*(cursor + 1)) == ';')) {
NegativeBlack 10:22d49341340c 139 command = Controller::C_Write;
NegativeBlack 10:22d49341340c 140 state = Controller::S_Index;
NegativeBlack 10:22d49341340c 141 cursor += 2;
NegativeBlack 10:22d49341340c 142 continue;
NegativeBlack 10:22d49341340c 143 }
NegativeBlack 10:22d49341340c 144
NegativeBlack 10:22d49341340c 145 return Controller::E_InvalidCommand;
NegativeBlack 10:22d49341340c 146 }
NegativeBlack 10:22d49341340c 147
NegativeBlack 10:22d49341340c 148 case Controller::S_Index: {
NegativeBlack 10:22d49341340c 149 if (std::sscanf(cursor, "%d;", &index) != 1) {
NegativeBlack 10:22d49341340c 150 return Controller::E_InvalidFormat;
NegativeBlack 10:22d49341340c 151 }
NegativeBlack 10:22d49341340c 152
NegativeBlack 10:22d49341340c 153 char *offset = std::strchr(cursor, ';');
NegativeBlack 10:22d49341340c 154 if (offset == NULL) {
NegativeBlack 10:22d49341340c 155 return Controller::E_InvalidFormat;
NegativeBlack 10:22d49341340c 156 }
NegativeBlack 10:22d49341340c 157
NegativeBlack 10:22d49341340c 158 cursor = offset + 1;
NegativeBlack 10:22d49341340c 159 state = Controller::S_Execute;
NegativeBlack 10:22d49341340c 160 continue;
NegativeBlack 10:22d49341340c 161 }
NegativeBlack 10:22d49341340c 162
NegativeBlack 10:22d49341340c 163 case Controller::S_Execute: {
NegativeBlack 10:22d49341340c 164 switch (command) {
NegativeBlack 10:22d49341340c 165 case Controller::C_Read: {
NegativeBlack 10:22d49341340c 166 DigitalIn *input = this->getInput(index);
NegativeBlack 10:22d49341340c 167 if (input == NULL) {
NegativeBlack 10:22d49341340c 168 return Controller::E_UnknownIndex;
NegativeBlack 10:22d49341340c 169 }
NegativeBlack 10:22d49341340c 170
NegativeBlack 10:22d49341340c 171 response.setLength(std::snprintf(
NegativeBlack 10:22d49341340c 172 (char *)response.pointer(), response.size(),
NegativeBlack 10:22d49341340c 173 "r;%d;%d;", index, input->read()));
NegativeBlack 10:22d49341340c 174
NegativeBlack 10:22d49341340c 175 if (response.length() < 6) {
NegativeBlack 10:22d49341340c 176 printf("Warning: failed to format reply.\n\r");
NegativeBlack 10:22d49341340c 177 return Controller::E_Internal;
NegativeBlack 10:22d49341340c 178 }
NegativeBlack 10:22d49341340c 179
NegativeBlack 10:22d49341340c 180 if (this->_network.client.write(response) < 0) {
NegativeBlack 10:22d49341340c 181 printf("Warning: failed to reply on read request.\n\r");
NegativeBlack 10:22d49341340c 182 return Controller::E_Internal;
NegativeBlack 10:22d49341340c 183 }
NegativeBlack 10:22d49341340c 184
NegativeBlack 10:22d49341340c 185 if ((*cursor) == 0 || (*(cursor + 1)) == 0) {
NegativeBlack 10:22d49341340c 186 return 0;
NegativeBlack 10:22d49341340c 187 }
NegativeBlack 10:22d49341340c 188
NegativeBlack 10:22d49341340c 189 command = Controller::C_None;
NegativeBlack 10:22d49341340c 190 state = Controller::S_Init;
NegativeBlack 10:22d49341340c 191 continue;
NegativeBlack 10:22d49341340c 192 }
NegativeBlack 10:22d49341340c 193
NegativeBlack 10:22d49341340c 194 case Controller::C_Write: {
NegativeBlack 10:22d49341340c 195 DigitalOut *output = this->getOutput(index);
NegativeBlack 10:22d49341340c 196 if (output == NULL) {
NegativeBlack 10:22d49341340c 197 return Controller::E_UnknownIndex;
NegativeBlack 10:22d49341340c 198 }
NegativeBlack 10:22d49341340c 199
NegativeBlack 10:22d49341340c 200 int value = 0;
NegativeBlack 10:22d49341340c 201 if (std::sscanf(cursor, "%d;", &value) != 1) {
NegativeBlack 10:22d49341340c 202 return Controller::E_InvalidFormat;
NegativeBlack 10:22d49341340c 203 }
NegativeBlack 10:22d49341340c 204
NegativeBlack 10:22d49341340c 205 char *offset = std::strchr(cursor, ';');
NegativeBlack 10:22d49341340c 206 if (offset == NULL) {
NegativeBlack 10:22d49341340c 207 return Controller::E_InvalidFormat;
NegativeBlack 10:22d49341340c 208 }
NegativeBlack 10:22d49341340c 209 cursor = offset + 1;
NegativeBlack 10:22d49341340c 210
NegativeBlack 10:22d49341340c 211 if (value != 0 && value != 1) {
NegativeBlack 10:22d49341340c 212 return Controller::E_InvalidValue;
NegativeBlack 10:22d49341340c 213 }
NegativeBlack 10:22d49341340c 214
NegativeBlack 10:22d49341340c 215 output->write(value);
NegativeBlack 10:22d49341340c 216
NegativeBlack 10:22d49341340c 217 if ((*cursor) == 0 || (*(cursor + 1)) == 0) {
NegativeBlack 10:22d49341340c 218 return 0;
NegativeBlack 10:22d49341340c 219 }
NegativeBlack 10:22d49341340c 220
NegativeBlack 10:22d49341340c 221 command = Controller::C_None;
NegativeBlack 10:22d49341340c 222 state = Controller::S_Init;
NegativeBlack 10:22d49341340c 223 continue;
NegativeBlack 10:22d49341340c 224 }
NegativeBlack 10:22d49341340c 225 }
NegativeBlack 10:22d49341340c 226 }
NegativeBlack 10:22d49341340c 227 }
NegativeBlack 10:22d49341340c 228 }
NegativeBlack 10:22d49341340c 229
NegativeBlack 10:22d49341340c 230 return 0;
NegativeBlack 10:22d49341340c 231 }
NegativeBlack 10:22d49341340c 232
NegativeBlack 10:22d49341340c 233
NegativeBlack 10:22d49341340c 234 int
NegativeBlack 10:22d49341340c 235 Controller::addOutput(DigitalOut *output)
NegativeBlack 10:22d49341340c 236 {
NegativeBlack 10:22d49341340c 237 if (this->_outputExists(output)) {
NegativeBlack 10:22d49341340c 238 return false;
NegativeBlack 10:22d49341340c 239 }
NegativeBlack 10:22d49341340c 240
NegativeBlack 10:22d49341340c 241 this->_io.output.push_back(output);
NegativeBlack 10:22d49341340c 242 return true;
NegativeBlack 10:22d49341340c 243 }
NegativeBlack 10:22d49341340c 244
NegativeBlack 10:22d49341340c 245 int
NegativeBlack 10:22d49341340c 246 Controller::addInput(DigitalIn *input)
NegativeBlack 10:22d49341340c 247 {
NegativeBlack 10:22d49341340c 248 if (this->_inputExists(input)) {
NegativeBlack 10:22d49341340c 249 return false;
NegativeBlack 10:22d49341340c 250 }
NegativeBlack 10:22d49341340c 251
NegativeBlack 10:22d49341340c 252 this->_io.input.push_back(input);
NegativeBlack 10:22d49341340c 253 return true;
NegativeBlack 10:22d49341340c 254 }
NegativeBlack 10:22d49341340c 255
NegativeBlack 10:22d49341340c 256 DigitalOut *
NegativeBlack 10:22d49341340c 257 Controller::getOutput(size_t index)
NegativeBlack 10:22d49341340c 258 {
NegativeBlack 10:22d49341340c 259 Controller::DigitalOutputList::iterator output;
NegativeBlack 10:22d49341340c 260 output = this->_io.output.begin();
NegativeBlack 10:22d49341340c 261 output = output + (int)index;
NegativeBlack 10:22d49341340c 262
NegativeBlack 10:22d49341340c 263 if (output >= this->_io.output.end()) {
NegativeBlack 10:22d49341340c 264 return NULL;
NegativeBlack 10:22d49341340c 265 }
NegativeBlack 10:22d49341340c 266
NegativeBlack 10:22d49341340c 267 return (*output);
NegativeBlack 10:22d49341340c 268 }
NegativeBlack 10:22d49341340c 269
NegativeBlack 10:22d49341340c 270 DigitalIn *
NegativeBlack 10:22d49341340c 271 Controller::getInput(size_t index)
NegativeBlack 10:22d49341340c 272 {
NegativeBlack 10:22d49341340c 273 DigitalInputList::iterator input;
NegativeBlack 10:22d49341340c 274 input = this->_io.input.begin();
NegativeBlack 10:22d49341340c 275 input = input + (int)index;
NegativeBlack 10:22d49341340c 276
NegativeBlack 10:22d49341340c 277 if (input >= this->_io.input.end()) {
NegativeBlack 10:22d49341340c 278 return NULL;
NegativeBlack 10:22d49341340c 279 }
NegativeBlack 10:22d49341340c 280
NegativeBlack 10:22d49341340c 281 return (*input);
NegativeBlack 10:22d49341340c 282 }
NegativeBlack 10:22d49341340c 283
NegativeBlack 10:22d49341340c 284 bool
NegativeBlack 10:22d49341340c 285 Controller::_outputExists(DigitalOut *output)
NegativeBlack 10:22d49341340c 286 {
NegativeBlack 10:22d49341340c 287 DigitalOutputList::iterator entry;
NegativeBlack 10:22d49341340c 288 entry = this->_io.output.begin();
NegativeBlack 10:22d49341340c 289 for (;entry != this->_io.output.end(); entry++) {
NegativeBlack 10:22d49341340c 290 if (output == (*entry)) {
NegativeBlack 10:22d49341340c 291 return true;
NegativeBlack 10:22d49341340c 292 }
NegativeBlack 10:22d49341340c 293 }
NegativeBlack 10:22d49341340c 294
NegativeBlack 10:22d49341340c 295 return false;
NegativeBlack 10:22d49341340c 296 }
NegativeBlack 10:22d49341340c 297
NegativeBlack 10:22d49341340c 298 bool
NegativeBlack 10:22d49341340c 299 Controller::_inputExists(DigitalIn *input)
NegativeBlack 10:22d49341340c 300 {
NegativeBlack 10:22d49341340c 301 Controller::DigitalInputList::iterator entry;
NegativeBlack 10:22d49341340c 302 entry = this->_io.input.begin();
NegativeBlack 10:22d49341340c 303 for (;entry != this->_io.input.end(); entry++) {
NegativeBlack 10:22d49341340c 304 if (input == (*entry)) {
NegativeBlack 10:22d49341340c 305 return true;
NegativeBlack 10:22d49341340c 306 }
NegativeBlack 10:22d49341340c 307 }
NegativeBlack 10:22d49341340c 308
NegativeBlack 10:22d49341340c 309 return false;
NegativeBlack 10:22d49341340c 310 }