You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
7.8 KiB
393 lines
7.8 KiB
|
|
|
|
#include "modelbahn.h"
|
|
#include "interface.h"
|
|
|
|
// **************************************************************************
|
|
// *
|
|
// * I N T E R F A C E (gateway to different devices)
|
|
// *
|
|
// **************************************************************************
|
|
|
|
Interface::Interface() {
|
|
name[0] = 0;
|
|
host[0] = 0;
|
|
flags = 0;
|
|
type = INTF_T_OFF_UNKNOWN;
|
|
needs_update = true;
|
|
};
|
|
|
|
Interface::~Interface() {
|
|
};
|
|
|
|
|
|
void Interface::Connect () {
|
|
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) Connect to %s", name, host);
|
|
|
|
switch (type) {
|
|
case INTF_T_Z21: intz21.Connect(host); break;
|
|
default: break;
|
|
}
|
|
};
|
|
|
|
|
|
void Interface::Disconnect() {
|
|
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) Disconnect", name);
|
|
|
|
switch (type) {
|
|
case INTF_T_Z21: intz21.Disconnect(); break;
|
|
default: break;
|
|
}
|
|
};
|
|
|
|
|
|
void Interface::PowerOnOff(int onoff) {
|
|
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) PowerOnOff %d", name, onoff);
|
|
|
|
switch (type) {
|
|
case INTF_T_Z21: intz21.PowerOnOff(onoff); break;
|
|
default: break;
|
|
}
|
|
};
|
|
|
|
//
|
|
// Turnout
|
|
//
|
|
void Interface::SetTurnout(Turnout *t, int active, int motoractive) {
|
|
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) SetTurnout Addr:%d FinalAcitve:%d Motor:%d", name,
|
|
t->addr, active, motoractive);
|
|
|
|
switch (type) {
|
|
case INTF_T_Z21: intz21.SetTurnout(t, active, motoractive); break;
|
|
default: break;
|
|
}
|
|
|
|
//
|
|
// make sure we turn the motor later off
|
|
if (motoractive) t->flags |= TURNOUT_F_ACTIVE;
|
|
else t->flags &= ~TURNOUT_F_ACTIVE;
|
|
gettimeofday (&t->activatetime, NULL);
|
|
};
|
|
|
|
//
|
|
// Locomotive
|
|
//
|
|
void Interface::SetLocoSpeed(Locomotive *l, int step) {
|
|
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) SetLocoSpeed Addr:%d Speed:%d ", name, l->addr, step);
|
|
|
|
switch (type) {
|
|
case INTF_T_Z21: intz21.SetLocoSpeed(l, step); break;
|
|
default: break;
|
|
}
|
|
};
|
|
|
|
|
|
void Interface::SetLocoFunction(Locomotive *l, int func, int value) {
|
|
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) SetLocoFunction Addr:%d Func:%d:%d", name, l->addr, func, value);
|
|
|
|
switch (type) {
|
|
case INTF_T_Z21: intz21.SetLocoFunction(l, func, value); break;
|
|
default: break;
|
|
}
|
|
};
|
|
|
|
|
|
int Interface::Loop() {
|
|
int ret = 0;
|
|
|
|
flags &= ~(INTF_F_CONNECTED | INTF_F_POWER | INTF_F_STOP | INTF_F_SHORT_CIRCUIT | INTF_F_PROGRAMMING);
|
|
if (needs_update) {
|
|
ret = 1;
|
|
needs_update = 0;
|
|
}
|
|
|
|
switch (type) {
|
|
case INTF_T_Z21:
|
|
ret = intz21.Loop(name);
|
|
if (intz21.IsConnected()) flags |= INTF_F_CONNECTED;
|
|
if (intz21.IsPoweron()) flags |= INTF_F_POWER;
|
|
if (intz21.IsEmergencyStop()) flags |= INTF_F_STOP;
|
|
if (intz21.IsSortCircuit()) flags |= INTF_F_SHORT_CIRCUIT;
|
|
break;
|
|
default: break;
|
|
}
|
|
|
|
// debug (DEBUG_INFO | DEBUG_IFACE, "%s:%d Interface: name:'%s' , Flags: %d", __FILE__, __LINE__, name, flags);
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
bool Interface::IsConnected() {
|
|
bool ret = false;
|
|
|
|
switch (type) {
|
|
case INTF_T_Z21: ret = intz21.IsConnected(); break;
|
|
default: break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
bool Interface::IsPoweron() {
|
|
bool ret = false;
|
|
|
|
switch (type) {
|
|
case 1: ret = intz21.IsPoweron(); break;
|
|
default: break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
// **************************************************************************
|
|
// *
|
|
// * I N T E R F A C E S (gateway to all devices)
|
|
// *
|
|
// **************************************************************************
|
|
|
|
Interfaces::Interfaces () {
|
|
max = INTERFACES_MAX;
|
|
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();
|
|
|
|
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].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].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].name[0] != 0) {
|
|
// 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) {
|
|
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].name[0] != 0) {
|
|
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;
|
|
changed = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
UnLockThread();
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
void Interfaces::PowerOnOff(int onoff) {
|
|
int i;
|
|
|
|
LockThread();
|
|
|
|
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
|
|
if (!interfaces[i].IsConnected()) interfaces[i].Connect();
|
|
interfaces[i].PowerOnOff(onoff);
|
|
}
|
|
|
|
UnLockThread();
|
|
};
|
|
|
|
//
|
|
// Turnouts
|
|
//
|
|
|
|
void Interfaces::SetTurnout(Turnout *t, int active, int motoractive) {
|
|
int i;
|
|
|
|
LockThread();
|
|
|
|
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
|
|
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;
|
|
|
|
if (abs(speed) < l->vmin) step = 0;
|
|
if (abs(speed) >= l->vmin) step = (speed * (l->steps-1)) / l->vmax;
|
|
if (abs(speed) > l->vmax) step = l->steps-1;
|
|
|
|
l->speed = speed;
|
|
|
|
LockThread();
|
|
|
|
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
|
|
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].name[0] != 0) {
|
|
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].name[0] != 0) {
|
|
if (interfaces[i].Loop()) {
|
|
//
|
|
// now we need to send an update
|
|
jout.Clear();
|
|
jout.AddObject ("interface", _GetJSON(i));
|
|
if (network) network->ChangeListPushToAll(jout.ToString());
|
|
}
|
|
}
|
|
};
|
|
|