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.
263 lines
6.1 KiB
263 lines
6.1 KiB
|
|
#include "modelbahn.h"
|
|
#include "turnout.h"
|
|
|
|
Turnouts::Turnouts() {
|
|
changed = 0;
|
|
turnouts = (Turnout*) malloc(sizeof(Turnout)*TURNOUTS_MAX);
|
|
max = TURNOUTS_MAX;
|
|
};
|
|
|
|
Turnouts::~Turnouts() {
|
|
free (turnouts);
|
|
max = 0;
|
|
turnouts = NULL;
|
|
};
|
|
|
|
|
|
int Turnouts::Lock() {
|
|
if (pthread_mutex_lock(&mtx) == 0) return 1;
|
|
else return 0;
|
|
}
|
|
|
|
|
|
int Turnouts::UnLock() {
|
|
if (pthread_mutex_unlock(&mtx) == 0) return 1;
|
|
else return 0;
|
|
}
|
|
|
|
|
|
JSONParse Turnouts::_GetJSON(int idx) {
|
|
JSONParse json;
|
|
JSONElement je;
|
|
string s = "";
|
|
|
|
json.Clear();
|
|
|
|
s = turnouts[idx].name; json.AddObject("name", s);
|
|
s = turnouts[idx].ifname; json.AddObject("ifname", s);
|
|
json.AddObject("addr", turnouts[idx].addr);
|
|
json.AddObject("activetimeout", turnouts[idx].activetimeout);
|
|
json.AddObject("flags", turnouts[idx].flags);
|
|
|
|
return json;
|
|
};
|
|
|
|
|
|
JSONParse Turnouts::GetJSON(string name) {
|
|
int i;
|
|
JSONParse jp;
|
|
|
|
jp.Clear();
|
|
|
|
Lock();
|
|
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
|
|
if (name.compare(turnouts[i].name) == 0) {
|
|
jp = _GetJSON(i);
|
|
}
|
|
}
|
|
|
|
UnLock();
|
|
|
|
return jp;
|
|
};
|
|
|
|
|
|
void Turnouts::GetJSONAll(JSONParse *json) {
|
|
int i, cnt;
|
|
JSONElement je;
|
|
|
|
Lock();
|
|
|
|
//
|
|
// write all railway data
|
|
// create json object array manualy
|
|
je.type = JSON_T_ARRAY;
|
|
je.name = "turnouts";
|
|
for (cnt = 0, i = 0; i < max; i++)
|
|
if (turnouts[i].name[0] != 0) {
|
|
if (cnt != 0) je.value += ","; // not first element
|
|
je.value += _GetJSON(i).ToString();
|
|
cnt++;
|
|
}
|
|
json->AddObject(je);
|
|
|
|
UnLock();
|
|
};
|
|
|
|
|
|
Turnout Turnouts::GetTurnoutFromJSON(JSONParse *j) {
|
|
Turnout to;
|
|
string s;
|
|
|
|
to.name[0] = 0;
|
|
to.ifname[0] = 0;
|
|
to.addr = 0;
|
|
to.activetimeout = TURNOUT_DEFAULT_ACTIVETIMEOUT; // default active timeout in MS
|
|
to.flags = 0;
|
|
|
|
j->GetValue("name", &s);
|
|
strncpy (to.name, s.c_str(), REFERENCENAME_LEN);
|
|
j->GetValue("ifname", &s);
|
|
strncpy (to.ifname, s.c_str(), REFERENCENAME_LEN);
|
|
j->GetValueInt("addr", &to.addr);
|
|
j->GetValueInt("activetimeout", &to.activetimeout);
|
|
j->GetValueInt("flags", &to.flags);
|
|
|
|
return to;
|
|
};
|
|
|
|
|
|
int Turnouts::Change(Turnout *to) {
|
|
int i;
|
|
int ifree = -1;
|
|
|
|
Lock();
|
|
|
|
for (i = 0; i < max; i++) {
|
|
if (turnouts[i].name[0] != 0) {
|
|
// found element
|
|
if (strncmp(turnouts[i].name, to->name, REFERENCENAME_LEN) == 0) {
|
|
ifree = i;
|
|
break;
|
|
}
|
|
}
|
|
else if (ifree == -1) ifree = i;
|
|
}
|
|
// element not found add new element
|
|
if (ifree != -1 && ifree < max) {
|
|
turnouts[ifree] = *to;
|
|
strncpy (turnouts[ifree].name, to->name, REFERENCENAME_LEN);
|
|
strncpy (turnouts[ifree].ifname, to->ifname, REFERENCENAME_LEN);
|
|
turnouts[ifree].activetimeout = to->activetimeout;
|
|
}
|
|
|
|
changed = 1;
|
|
UnLock();
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
int Turnouts::Delete(string name) {
|
|
int i;
|
|
|
|
Lock();
|
|
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
|
|
if (name.compare(turnouts[i].name) == 0) {
|
|
turnouts[i].name[0] = 0;
|
|
turnouts[i].ifname[0] = 0;
|
|
turnouts[i].addr = 0;
|
|
turnouts[i].flags = 0;
|
|
turnouts[i].activetimeout = TURNOUT_DEFAULT_ACTIVETIMEOUT;
|
|
changed = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
UnLock();
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
int Turnouts::Set(string name, int value) {
|
|
int i;
|
|
|
|
//
|
|
Lock();
|
|
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
|
|
if (name.compare(turnouts[i].name) == 0) {
|
|
debug (0, "Turnout::Set: Name:%s Flags:%d[%c%c%c] Value:%d", name.c_str(), turnouts[i].flags,
|
|
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-',
|
|
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
|
|
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
|
|
value);
|
|
if (turnouts[i].flags & TURNOUT_F_INVERSE)
|
|
server->interfaces.SetTurnout(&turnouts[i], !value, 1); // motor on
|
|
else
|
|
server->interfaces.SetTurnout(&turnouts[i], value, 1); // motor on
|
|
gettimeofday (&turnouts[i].activatetime, NULL);
|
|
changed = 1;
|
|
|
|
break;
|
|
}
|
|
}
|
|
UnLock();
|
|
|
|
return 1;
|
|
};
|
|
|
|
//
|
|
// got some data from bus
|
|
void Turnouts::SetFromBus(string ifname, int addr, int value) {
|
|
int i;
|
|
JSONParse jp;
|
|
|
|
debug (0, "Turnouts::SetFromBus Interface:%s, addr: %d, value:%d", ifname.c_str(), addr, value);
|
|
|
|
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
|
|
if (ifname.compare(turnouts[i].ifname) == 0 && turnouts[i].addr == addr) {
|
|
debug (0, "Turnout::SetFromBus Name:%s Flags:%d[%c%c%c]", turnouts[i].name, turnouts[i].flags,
|
|
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-',
|
|
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
|
|
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-');
|
|
|
|
// if (value) turnouts[i].flags |= TURNOUT_F_ACTIVE;
|
|
// else turnouts[i].flags &= ~TURNOUT_F_ACTIVE;
|
|
|
|
if (turnouts[i].flags & TURNOUT_F_INVERSE) {
|
|
if (value) turnouts[i].flags &= ~TURNOUT_F_TURNOUT;
|
|
else turnouts[i].flags |= TURNOUT_F_TURNOUT;
|
|
}
|
|
else {
|
|
if (value) turnouts[i].flags |= TURNOUT_F_TURNOUT;
|
|
else turnouts[i].flags &= ~TURNOUT_F_TURNOUT;
|
|
}
|
|
debug (0, "Turnout::SetFromBus Name:%s Flags:%d[%c%c%c]", turnouts[i].name, turnouts[i].flags,
|
|
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-',
|
|
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
|
|
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-');
|
|
|
|
jp.AddObject("turnout", _GetJSON(i));
|
|
if(network) network->ChangeListPushToAll(jp.ToString());
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
//
|
|
// this loop is important: Turnout motors needs to be deactivated after a short time
|
|
//
|
|
void Turnouts::Loop() {
|
|
int i;
|
|
struct timeval curtime;
|
|
|
|
gettimeofday(&curtime, NULL);
|
|
|
|
Lock();
|
|
|
|
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
|
|
if (turnouts[i].flags & TURNOUT_F_ACTIVE) {
|
|
//
|
|
// motor still active check timeout and deactivate
|
|
int timediff = (1000 * (curtime.tv_sec - turnouts[i].activatetime.tv_sec)) +
|
|
((curtime.tv_usec - turnouts[i].activatetime.tv_usec) / 1000);
|
|
if (timediff < 0) gettimeofday (&turnouts[i].activatetime, NULL);
|
|
|
|
// debug (0, "%s:%d timediff: %d", __FILE__, __LINE__, timediff);
|
|
|
|
if (timediff > turnouts[i].activetimeout) {
|
|
int active = turnouts[i].flags & TURNOUT_F_TURNOUT;
|
|
if (turnouts[i].flags & TURNOUT_F_INVERSE)
|
|
server->interfaces.SetTurnout(&turnouts[i], !active, 0); // motor on
|
|
else
|
|
server->interfaces.SetTurnout(&turnouts[i], active, 0); // motor on
|
|
turnouts[i].flags &= ~TURNOUT_F_ACTIVE;
|
|
}
|
|
}
|
|
}
|
|
UnLock();
|
|
};
|