diff --git a/server/interfaces.cc b/server/interfaces.cc new file mode 100644 index 0000000..8b82867 --- /dev/null +++ b/server/interfaces.cc @@ -0,0 +1,270 @@ + +#include "modelbahn.h" +#include "interface.h" +#include "interface-z21.h" +#include "interfaces.h" + + +// ************************************************************************** +// * +// * I N T E R F A C E S (gateway to all devices) +// * +// ************************************************************************** + +Interfaces::Interfaces () { + max = INTERFACES_MAX; + for (int i = 0; i < max; i++) interfaces[i] = NULL; + changed = 0; +}; + +Interfaces::~Interfaces() { + max = 0; +}; + + +int Interfaces::LockThread() { + if (pthread_mutex_lock(&mtx) == 0) return 1; + else return 0; +} + + +int Interfaces::UnLockThread() { + if (pthread_mutex_unlock(&mtx) == 0) return 1; + else return 0; +} + + +JSONParse Interfaces::_GetJSON(int idx) { + JSONParse json; + JSONElement je; + string s = ""; + + json.Clear(); + + if (interfaces[idx] != NULL) { + s = interfaces[idx]->name; json.AddObject("name", s); + s = interfaces[idx]->host; json.AddObject("host", s); + json.AddObject("flags", interfaces[idx]->flags); + json.AddObject("type", interfaces[idx]->type); + } + + return json; +}; + + +JSONParse Interfaces::GetJSON(string name) { + int i; + JSONParse jp; + + jp.Clear(); + + LockThread(); + for (i = 0; i < max; i++) if (interfaces[i] != NULL){ + if (interfaces[i]->name[0] != 0) { + if (name.compare(interfaces[i]->name) == 0) { + jp = _GetJSON(i); + } + } + } + UnLockThread(); + + return jp; +}; + + +void Interfaces::GetJSONAll(JSONParse *json) { + int i, cnt; + JSONElement je; + + LockThread(); + + // + // write all railway data + // create json object array manualy + je.type = JSON_T_ARRAY; + je.name = "interfaces"; + for (cnt = 0, i = 0; i < max; i++) if(interfaces[i] != NULL) + if (interfaces[i]->name[0] != 0) { + if (cnt != 0) je.value += ","; // not first element + je.value += _GetJSON(i).ToString(); + cnt++; + } + json->AddObject(je); + + UnLockThread(); +}; + + +Interface Interfaces::GetInterfaceFromJSON(JSONParse *j) { + Interface i; + string s; + + i.name[0] = 0; + i.host[0] = 0; + + j->GetValue("name", &s); + strncpy (i.name, s.c_str(), REFERENCENAME_LEN); + j->GetValue("host", &s); + strncpy (i.host, s.c_str(), REFERENCENAME_LEN); + j->GetValueInt("flags", &i.flags); + j->GetValueInt("type", &i.type); + + return i; +}; + + +int Interfaces::Change(Interface *iface) { + int i; + int ifree = -1; + + LockThread(); + for (i = 0; i < max; i++) { + if (interfaces[i] != NULL) { + // found element + if (strncmp(interfaces[i]->name, iface->name, REFERENCENAME_LEN) == 0) { + ifree = i; + break; + } + } + else if (ifree == -1) ifree = i; + } + + // element not found add new element + if (ifree != -1 && ifree < max) { + if (iface->type == INTF_T_Z21) interfaces[ifree] = new InterfaceZ21(); + else interfaces[ifree] = new Interface(); + strncpy (interfaces[ifree]->name, iface->name, REFERENCENAME_LEN); + strncpy (interfaces[ifree]->host, iface->host, REFERENCENAME_LEN); + interfaces[ifree]->flags = iface->flags; + interfaces[ifree]->type = iface->type; + interfaces[ifree]->Connect(); + } + changed = 1; + UnLockThread(); + + return 1; +}; + + +int Interfaces::Delete(string name) { + int i; + + LockThread(); + for (i = 0; i < max; i++) if (interfaces[i] != NULL) { + if (name.compare(interfaces[i]->name) == 0) { + interfaces[i]->Disconnect(); + interfaces[i]->name[0] = 0; + interfaces[i]->host[0] = 0; + interfaces[i]->flags = 0; + interfaces[i]->type = INTF_T_OFF_UNKNOWN; + delete interfaces[i]; + interfaces[i] = NULL; + changed = 1; + break; + } + } + + UnLockThread(); + + return 1; +}; + + +void Interfaces::PowerOnOff(int onoff) { + int i; + + LockThread(); + + for (i = 0; i < max; i++) if (interfaces[i] != NULL) { + if (!interfaces[i]->IsConnected()) interfaces[i]->Connect(); + interfaces[i]->PowerOnOff(onoff); + } + + UnLockThread(); +}; + + +// +// Turnouts +// +void Interfaces::SetTurnout(Turnout *t, int active, int motoractive) { + int i; + + if (t == NULL) return; + + LockThread(); + debug (0, "%s:%d Interfaces::SetTurnout Name:%s active:%d Output%d", __FILE__, __LINE__, t->name, active, motoractive); + + for (i = 0; i < max; i++) if (interfaces[i] != NULL) { + if (!interfaces[i]->IsConnected()) interfaces[i]->Connect(); + if (strncmp(t->ifname, interfaces[i]->name, REFERENCENAME_LEN) == 0) + interfaces[i]->SetTurnout(t, active, motoractive); + } + + UnLockThread(); +}; + + +// +// Locomotives +// +void Interfaces::SetLocoSpeed(Locomotive *l, int speed) { + int i; + int step = 0, maxstep = 0; + + switch(l->stepcode) { + case LOCO_INT_DCC14: maxstep = 14; break; + case LOCO_INT_DCC28: maxstep = 28; break; + case LOCO_INT_DCC128: maxstep = 126; break; + default: maxstep = 0; break; + } + + if (abs(speed) < l->vmin) step = 0; + if (abs(speed) >= l->vmin) step = (speed * (maxstep)) / l->vmax; + if (abs(speed) > l->vmax) step = maxstep; + + l->speed = speed; + + LockThread(); + + for (i = 0; i < max; i++) if (interfaces[i] != NULL) { + if (!interfaces[i]->IsConnected()) interfaces[i]->Connect(); + if (strncmp(l->ifname, interfaces[i]->name, REFERENCENAME_LEN) == 0) + interfaces[i]->SetLocoSpeed(l, step); + } + + UnLockThread(); +}; + + +void Interfaces::SetLocoFunction(Locomotive *l, int func, int value) { + int i; + + LockThread(); + + for (i = 0; i < max; i++) if (interfaces[i] != NULL) { + if (!interfaces[i]->IsConnected()) interfaces[i]->Connect(); + if (strncmp(l->ifname, interfaces[i]->name, REFERENCENAME_LEN) == 0) + interfaces[i]->SetLocoFunction(l, func, value); + } + + UnLockThread(); +}; + + + +void Interfaces::Loop() { + int i; + JSONParse jout; + + for (i = 0; i < max; i++) if (interfaces[i] != NULL) { + if (interfaces[i]->Loop()) { + // + // now we need to send an update + jout.Clear(); + jout.AddObject ("interface", _GetJSON(i)); + if (network) network->ChangeListPushToAll(jout.ToString()); + } + } +}; + diff --git a/server/interfaces.h b/server/interfaces.h new file mode 100644 index 0000000..d0f1bd6 --- /dev/null +++ b/server/interfaces.h @@ -0,0 +1,87 @@ + +#ifndef _INTERFACE_H_ +#define _INTERFACE_H_ + +#include "modelbahn.h" +#include "server.h" +#include "UDPTCPNetwork.h" +#include "json.h" +#include "interface-z21.h" + +#define INTF_F_CONNECTED 0x0001 +#define INTF_F_POWER 0x0002 +#define INTF_F_STOP 0x0004 +#define INTF_F_SHORT_CIRCUIT 0x0008 +#define INTF_F_PROGRAMMING 0x0010 +#define INTF_F_NEEDUPDATE 0x8000 // if something changes during the Loop + +#define INTF_T_OFF_UNKNOWN 0 +#define INTF_T_Z21 1 + + +class Interface { +private: + InterfaceZ21 intz21; + bool needs_update; + struct timeval turnouttimeout; +public: + char name[REFERENCENAME_LEN]; + char host[NET_HOSTLEN]; + int flags; + int type; + + Interface(); + virtual ~Interface(); + + virtual void Connect(); + virtual void Disconnect(); + + virtual void PowerOnOff(int onoff); + virtual void SetLocoSpeed(Locomotive *l, int step); + virtual void SetLocoFunction(Locomotive *l, int func, int value); + virtual void SetTurnout(Turnout *t, int active, int motoractive); + + virtual bool IsConnected(); + virtual bool IsPoweron(); + + virtual int Loop(); +}; + + +class Interfaces { + private: + Interface *interfaces[INTERFACES_MAX]; + int max; + int changed; + + pthread_mutex_t mtx; + int LockThread(); + int UnLockThread(); + + // not thread safe + JSONParse _GetJSON(int idx); + public: + Interfaces(); + ~Interfaces(); + + bool IsChanged() { return changed; } + void ClearChanged() { changed = 0; }; + + int Change(Interface *iface); + int Delete(string name); + + JSONParse GetJSON(string name); + void GetJSONAll(JSONParse *json); + Interface GetInterfaceFromJSON(JSONParse *j); + + // + // + void PowerOnOff(int onoff); + void SetLocoSpeed(Locomotive *l, int speed); + void SetLocoFunction(Locomotive *l, int func, int value); + void SetTurnout(Turnout *t, int active, int outputactive); + + void Loop(); +}; + +#endif