ModBus TCP Implementation

Fork of HTTPD by AMETEK Powervar

Committer:
gulchi
Date:
Fri Jun 30 10:40:06 2017 +0000
Revision:
4:41ee166a0e6c
Parent:
3:ebea8e061ae6
updated license

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:d18dff347122 1 /* Copyright (C) 2013 Hiroshi Suga, MIT License
okini3939 0:d18dff347122 2 *
okini3939 0:d18dff347122 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
okini3939 0:d18dff347122 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
okini3939 0:d18dff347122 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
okini3939 0:d18dff347122 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
okini3939 0:d18dff347122 7 * furnished to do so, subject to the following conditions:
okini3939 0:d18dff347122 8 *
okini3939 0:d18dff347122 9 * The above copyright notice and this permission notice shall be included in all copies or
okini3939 0:d18dff347122 10 * substantial portions of the Software.
okini3939 0:d18dff347122 11 *
okini3939 0:d18dff347122 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
okini3939 0:d18dff347122 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
okini3939 0:d18dff347122 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
okini3939 0:d18dff347122 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
okini3939 0:d18dff347122 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
okini3939 0:d18dff347122 17 */
okini3939 0:d18dff347122 18
gulchi 2:fcd20e2cd110 19 #include "ModBus-TCP.h"
okini3939 0:d18dff347122 20
gulchi 2:fcd20e2cd110 21 Modbus * Modbus::_inst;
okini3939 0:d18dff347122 22
gulchi 2:fcd20e2cd110 23 Modbus::Modbus () {
okini3939 0:d18dff347122 24 _inst = this;
okini3939 0:d18dff347122 25 memset(_state, 0, sizeof(_state));
okini3939 0:d18dff347122 26 _handler_count = 0;
okini3939 0:d18dff347122 27 }
okini3939 0:d18dff347122 28
gulchi 3:ebea8e061ae6 29 int Modbus::start (EthernetInterface *ns, int port) {
okini3939 0:d18dff347122 30 int i;
okini3939 0:d18dff347122 31
dgriffin65 1:b724fdb741e7 32 m_ns = ns;
dgriffin65 1:b724fdb741e7 33
gulchi 2:fcd20e2cd110 34 for (i = 0; i < MODBUS_MAX_CLIENTS; i ++) {
gulchi 3:ebea8e061ae6 35 // _state[i].buf = new CircBuffer<char>(MODBUS_BUF_SIZE);
gulchi 2:fcd20e2cd110 36 _state[i].thread = new Thread(osPriorityNormal, MODBUS_STACK_SIZE);
dgriffin65 1:b724fdb741e7 37 _state[i].client = new TCPSocket();
dgriffin65 1:b724fdb741e7 38 _state[i].thread->start(callback(child, (void*)i));
okini3939 0:d18dff347122 39 }
dgriffin65 1:b724fdb741e7 40
gulchi 2:fcd20e2cd110 41 #ifdef MODBUS_ENABLE_CLOSER
gulchi 2:fcd20e2cd110 42 _state[MODBUS_MAX_CLIENTS].thread = new Thread(closer, (void*)MODBUS_MAX_CLIENTS, osPriorityNormal, 128);
gulchi 2:fcd20e2cd110 43 _state[MODBUS_MAX_CLIENTS].client = new TCPSocket(m_ns);
okini3939 0:d18dff347122 44 #endif
okini3939 0:d18dff347122 45
dgriffin65 1:b724fdb741e7 46 _server.open(m_ns);
okini3939 0:d18dff347122 47 _server.bind(port);
dgriffin65 1:b724fdb741e7 48 _server.set_blocking(true);
gulchi 3:ebea8e061ae6 49 _server.listen(MODBUS_MAX_CLIENTS);
gulchi 2:fcd20e2cd110 50 _daemon = new Thread(osPriorityNormal, MODBUS_STACK_SIZE);
gulchi 2:fcd20e2cd110 51 _daemon->start(Modbus::daemon);
okini3939 0:d18dff347122 52 return 0;
okini3939 0:d18dff347122 53 }
okini3939 0:d18dff347122 54
gulchi 2:fcd20e2cd110 55 void Modbus::daemon () {
gulchi 2:fcd20e2cd110 56 Modbus *modbus = Modbus::getInstance();
okini3939 0:d18dff347122 57 int i, t = 0;
okini3939 0:d18dff347122 58
gulchi 3:ebea8e061ae6 59
okini3939 0:d18dff347122 60 for (;;) {
gulchi 3:ebea8e061ae6 61 //DBG("Wait for new connection... child %i",t);
okini3939 0:d18dff347122 62 if (t >= 0) {
gulchi 2:fcd20e2cd110 63 if (modbus->_server.accept(modbus->_state[t].client) == 0) {
okini3939 0:d18dff347122 64 INFO("accept %d\r\n", t);
gulchi 3:ebea8e061ae6 65 modbus->_state[t].thread->signal_set(0x1);
okini3939 0:d18dff347122 66 }
okini3939 0:d18dff347122 67 } else {
okini3939 0:d18dff347122 68 #ifdef HTTPD_ENABLE_CLOSER
gulchi 2:fcd20e2cd110 69 if (modbus->_server.accept(modbus->_state[MODBUS_MAX_CLIENTS].client) == 0) {
okini3939 0:d18dff347122 70 INFO("accept x\r\n");
gulchi 3:ebea8e061ae6 71 modbus->_state[MODBUS_MAX_CLIENTS].thread->signal_set(0x1);
okini3939 0:d18dff347122 72 }
okini3939 0:d18dff347122 73 #endif
okini3939 0:d18dff347122 74 }
okini3939 0:d18dff347122 75
okini3939 0:d18dff347122 76 t = -1;
gulchi 2:fcd20e2cd110 77 for (i = 0; i < MODBUS_MAX_CLIENTS; i ++) {
gulchi 3:ebea8e061ae6 78 //DBG("Child %i in State : %u", i, modbus->_state[i].thread->get_state());
gulchi 3:ebea8e061ae6 79 if ( modbus->_state[i].thread->get_state() == Thread::WaitingThreadFlag) {
okini3939 0:d18dff347122 80 if (t < 0) t = i; // next empty thread
okini3939 0:d18dff347122 81 }
okini3939 0:d18dff347122 82 }
okini3939 0:d18dff347122 83 }
okini3939 0:d18dff347122 84 }
okini3939 0:d18dff347122 85
gulchi 2:fcd20e2cd110 86 void Modbus::child (void const *arg) {
gulchi 3:ebea8e061ae6 87 Modbus *modbus = Modbus::getInstance();
okini3939 0:d18dff347122 88 int id = (int)arg;
okini3939 0:d18dff347122 89 int i, n;
gulchi 3:ebea8e061ae6 90 char buf[MODBUS_BUF_SIZE];
okini3939 0:d18dff347122 91
okini3939 0:d18dff347122 92 for (;;) {
gulchi 3:ebea8e061ae6 93 //DBG("child %i waiting for connection",id);
gulchi 3:ebea8e061ae6 94 Thread::signal_wait(0x1);
gulchi 3:ebea8e061ae6 95
gulchi 3:ebea8e061ae6 96
gulchi 3:ebea8e061ae6 97
gulchi 3:ebea8e061ae6 98 INFO("Connection from client on child %i", id);
dgriffin65 1:b724fdb741e7 99 // INFO("Connection from %s\r\n", httpd->_state[id].client->get_ip_address());
dgriffin65 1:b724fdb741e7 100
gulchi 3:ebea8e061ae6 101 modbus->_state[id].client->set_blocking(true);
gulchi 3:ebea8e061ae6 102 modbus->_state[id].client->set_timeout(15000);
gulchi 3:ebea8e061ae6 103 time_t t1 = time(NULL);
okini3939 0:d18dff347122 104 for (;;) {
dgriffin65 1:b724fdb741e7 105 //if (! httpd->_state[id].client->is_connected()) break;
gulchi 3:ebea8e061ae6 106 modbus->_state[id].client->set_blocking(true);
gulchi 3:ebea8e061ae6 107 modbus->_state[id].client->set_timeout(15000);
gulchi 2:fcd20e2cd110 108 n = modbus->_state[id].client->recv(buf, sizeof(buf));
dgriffin65 1:b724fdb741e7 109
dgriffin65 1:b724fdb741e7 110 if (n < 0 ) {
gulchi 3:ebea8e061ae6 111 printf("Modbus::child breaking n = %d\r\n", n);
dgriffin65 1:b724fdb741e7 112 break;
dgriffin65 1:b724fdb741e7 113 }
gulchi 3:ebea8e061ae6 114
gulchi 3:ebea8e061ae6 115 if( n > 0 ) { // We received something
gulchi 3:ebea8e061ae6 116
gulchi 3:ebea8e061ae6 117 t1 = time(NULL);
gulchi 3:ebea8e061ae6 118
gulchi 3:ebea8e061ae6 119 //DBG("Recv %d bytes Content: %x", n, buf)
gulchi 3:ebea8e061ae6 120
gulchi 3:ebea8e061ae6 121 modbus->recvData(id, buf, n);
okini3939 0:d18dff347122 122 }
gulchi 3:ebea8e061ae6 123
gulchi 3:ebea8e061ae6 124 if(abs((int)(time(NULL) - t1))> 15) {
gulchi 3:ebea8e061ae6 125 DBG("Timeout in child %i",id);
gulchi 3:ebea8e061ae6 126 break;
gulchi 3:ebea8e061ae6 127 }
gulchi 3:ebea8e061ae6 128
okini3939 0:d18dff347122 129 }
okini3939 0:d18dff347122 130
gulchi 2:fcd20e2cd110 131 modbus->_state[id].client->close(); // Needs to bere moved
gulchi 3:ebea8e061ae6 132 INFO("Closed client connection");
dgriffin65 1:b724fdb741e7 133 //INFO("Close %s\r\n", httpd->_state[id].client->get_ip_address());
okini3939 0:d18dff347122 134 }
okini3939 0:d18dff347122 135 }
okini3939 0:d18dff347122 136
gulchi 2:fcd20e2cd110 137 void Modbus::closer (void const *arg) {
gulchi 2:fcd20e2cd110 138 Modbus *modbus = Modbus::getInstance();
okini3939 0:d18dff347122 139 int id = (int)arg;
okini3939 0:d18dff347122 140
okini3939 0:d18dff347122 141 for (;;) {
okini3939 0:d18dff347122 142 Thread::signal_wait(1);
okini3939 0:d18dff347122 143
gulchi 2:fcd20e2cd110 144 modbus->_state[id].client->close();
dgriffin65 1:b724fdb741e7 145 INFO("Closed client connection\r\n");
dgriffin65 1:b724fdb741e7 146 //INFO("Close %s\r\n", httpd->_state[id].client->get_ip_address());
okini3939 0:d18dff347122 147 }
okini3939 0:d18dff347122 148 }
okini3939 0:d18dff347122 149