Compare commits

..

1 Commits

Author SHA1 Message Date
steffen 029a707480 initial import
6 years ago

24
.gitignore vendored

@ -1,24 +0,0 @@
.cproject
.project
.settings
gmon.out
*/.depend
server/gmon.out
server/modelbahn-cgi
server/modelbahn-server
server/test-json
z21emu/gmon.out
z21emu/config.h
z21emu/z21emu
*~
*.oo
*.o
*.elf
*.bin
track.json
track.json.backup.*
Modelbahn.anjuta
*.track.json
Backup/
.anjuta_sym_db.db
.anjuta/

@ -1,3 +1,7 @@
2020-02-09:
- Züge fahren falsch herrum
- Speed und Fahrtrichtung werden nicht in den Zügen geupdated
- Max Speed ist nicht gleich der Maximalste Step

@ -1,96 +1,4 @@
2024-01-04:
- fixed: AutoCheckWaySingleStep: stops preparing way at next block
2024-01-16:
- fixed: not all pthread_mutexes has been initialization.
2023-12-30:
- fixed: FindWay will check for loops between two blocks
2023-12-27:
- split blocks do work.
- fixed issues with the way finding routine
2023-05-01:
- another work on the split blocks. long trains wont go into split blocks. Some final
checks are still needed to implement.
2023-04-02:
- fixed: track infomation is fixed.
- removed unneded debug file
2023-03-13:
- prepared split and short tracks. - needs to be tested completly.
2022-04-17:
- added "-simulation" parmeter for debugging purpose.
needed to simulate turnout manipulation
- fixed: locomotive AUTO->MAN mode is working if searching for a new way.
2022-02-13:
- Interfaces are now virtual classes.
2021-12-19:
- adding sensor context menu for sensor simulation
2021-12-10:
- adding support for scheduling ways
- fixed: webinterface, update on loco will now change its detail display
2021-12-02:
- mark blocks as onlyCARGO or onlyPESSANGER, random-automode looks nice now.
- webinterface: debug messages will be print to the console.
- webinterface: contextmenu will be displayed inside the visible area
2021-11-06:
- fixed: compiling error on compare with pointer
2021-03-09:
- changed: passenger trains (no cargo flag set) will always stop at stations.
- added station flag to blocks
- fixed: locomotives can not assigned to new block if on mode LOCO_F_AUTO
2021-03-07:
- fixed: high cpu load, sleep function was not working right. If the current
loop took below 1ms we would ot wait for the 25ms to finish.
2021-02-10:
- automatic mode with random destinations is working now
2021-01-31:
- automtic mode is improving, manual setting of destination
automatic routing and moving the train to the destination.
- locked turnouts can not anymore been set.
- assign loco and set destination is working now.
2021-01-19:
- threading should be now more stable no deadlocks
2021-01-15:
- web interface for block assignemt seems ready
- saving and loading data from a block.
2020-12-05:
- locomotive fixed division by zero
- webinterface: speed 0 was not displayed corecctly in ctrl screen.
2020-11-29:
- lococtrl display is now working with reverse and forward.
2020-04-25:
- reset seems to work fine now.
2020-03-22:
- adding server status messages
2020-03-06:
- fixed: speed and stepcoding
2020-03-03:
- adding new loco ctrl interface.
2020-02-09:
- Initial CVS Import

@ -1,9 +0,0 @@
TOPTARGETS := all clean
SUBDIRS := server
$(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@ $(MAKECMDGOALS)
.PHONY: $(TOPTARGETS) $(SUBDIRS)

@ -1,34 +0,0 @@
# Modelbahn
## Requirements:
Webserver with CGI enabled
## Installation:
+ copy the webinterface files to your location of the webserver
+ compile the server
+ copy the modelbahn-cgi binary to the cgi folder of the webserver
+ run the modelbahn-server application.
![Screenshot](https://steffen.gulpe.de/progs/modelbahn.png)
## Z21EMU and ATmega Sensors
Per default all devices get the same I2C defive address. As soon as the device is connected you should set up a new address for them. The following commands will set the device [0x2f] to address 0x31 and save this setting in the EPROM.
i2cset -y 1 0x2f 0x22 0x31
i2cset -y 1 0x2f 0x21 0x02
The following registers are used:
0x00 .. 0x08 INPUT and OUTPUT registers dependung on device
0x20 VERSION of the device
0x21 Command Register
0 no command
1 EEPROM read
2 EEPORM write
0x22 I2C Address
0x23 Input Off Delay

@ -0,0 +1,11 @@
Requirements:
- Webserver with CGI enabled
Installation:
- copy the webinterface files to your location of the webserver
- compile the server
- copy the modelbahn-cgi binary to the cgi folder of the webserver
- run the modelbahn-server application.

Binary file not shown.

@ -9,26 +9,26 @@ ETCPREFIX=/etc
DISTNAME=modelbahn
CXX=g++
CXXFLAGS= -Wall -ggdb -fPIC -Wno-write-strings -g -ggdb -std=c++11 -pg
LDFLAGS= -lm -lc -lpthread -L/usr/local/lib -g -ggdb -pg
CXXFLAGS= -ggdb -fPIC -Wno-write-strings -g -ggdb -std=c++11
LDFLAGS= -lm -lc -lpthread -L/usr/local/lib -g -ggdb
LDFLAGS_CGI= -lm -lc -lpthread -L/usr/local/lib -g -ggdb
DEPENDFILE=.depend
TARGET=modelbahn-server
SERVEROBJ=server.o network.o session.o server-loadsave.o debug.o \
json.o main.o sensor.o turnout.o railway.o interfaces.o locomotive.o \
block.o interface.o interface-z21.o
json.o main.o sensor.o turnout.o railway.o interface.o locomotive.o \
block.o interface-z21.o
CURDIR=`pwd`
all: dep $(TARGET) test-json modelbahn-cgi
modelbahn-server: $(SERVEROBJ)
$(CXX) -o $@ $^ $(LDFLAGS) -lUDPTCPNetwork -L./ -I./ -lpthread
$(CXX) -o $@ $^ $(LDFLAGS_CGI) -lUDPTCPNetwork -L./ -I./ -lpthread
modelbahn-cgi: modelbahn-cgi.o debug.o
$(CXX) -o $@ $^ $(LDFLAGS_CGI) -lUDPTCPNetwork -L./ -I./ -lpthread
$(CXX) -o $@ $^ $(LDFLAGS) -lUDPTCPNetwork -L./ -I./ -lpthread
test-json: json.o test-json.o debug.o
$(CXX) -o $@ $^ $(LDFLAGS) -L./ -I./ -lpthread

@ -1,21 +1,13 @@
#include <string>
#include "modelbahn.h"
#include "block.h"
#include <list>
#include <string>
#include <string.h>
using namespace std;
Blocks::Blocks () {
pthread_mutex_init(&mtx, NULL);
changed = 0;
blocks = (Block*) malloc(sizeof(Block)*SENSORS_MAX);
memset (blocks, 0x0, sizeof(Block)*SENSORS_MAX);
max = BLOCKS_MAX;
last_blockidx = -1;
};
Blocks::~Blocks() {
@ -39,27 +31,15 @@ int Blocks::UnLock() {
}
JSONParse Blocks::_GetJSON(Block *bl) {
JSONParse Blocks::_GetJSON(int idx) {
JSONParse json;
JSONElement je;
string s = "";
json.Clear();
json.AddObject("name", bl->name);
json.AddObject("flags", bl->flags);
json.AddObject("lockedby", bl->lockedby);
json.AddObject("sensor_enter_0", bl->s_enter[0]);
json.AddObject("sensor_slow_0", bl->s_slow[0]);
json.AddObject("sensor_stop_0", bl->s_stop[0]);
json.AddObject("sensor_shortstop_0", bl->s_shortstop[0]);
json.AddObject("sensor_enter_1", bl->s_enter[1]);
json.AddObject("sensor_slow_1", bl->s_slow[1]);
json.AddObject("sensor_stop_1", bl->s_stop[1]);
json.AddObject("sensor_shortstop_1", bl->s_shortstop[1]);
json.AddObject("secondblock", bl->secondblock);
s = blocks[idx].name; json.AddObject("name", s);
json.AddObject("flags", blocks[idx].flags);
return json;
};
@ -112,50 +92,12 @@ Block Blocks::GetBlockFromJSON(JSONParse *j) {
string s;
bl.name[0] = 0;
bl.secondblock[0] = 0;
bl.flags = 0;
bl.lockedby[0] = 0;
j->GetValue("name", &s);
strncpy (bl.name, s.c_str(), REFERENCENAME_LEN);
j->GetValueInt("flags", &bl.flags);
// j->GetValue("lockedby", &s);
// strncpy (bl.lockedby, s.c_str(), REFERENCENAME_LEN);
//
// old version input data
//
s = "";
if (j->GetValue("sensor_pos_1", &s)) {
strncpy (bl.s_enter[0], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_stop[1], s.c_str(), REFERENCENAME_LEN);
}
s = "";
if (j->GetValue("sensor_center", &s)) {
strncpy (bl.s_shortstop[0], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_shortstop[1], s.c_str(), REFERENCENAME_LEN);
}
s = "";
if (j->GetValue("sensor_neg_1", &s)) {
strncpy (bl.s_enter[1], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_stop[0], s.c_str(), REFERENCENAME_LEN);
}
//
// new version
//
s = ""; if (j->GetValue("sensor_enter_0", &s)) strncpy (bl.s_enter[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_enter_1", &s)) strncpy (bl.s_enter[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_slow_0", &s)) strncpy (bl.s_slow[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_slow_1", &s)) strncpy (bl.s_slow[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_stop_0", &s)) strncpy (bl.s_stop[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_stop_1", &s)) strncpy (bl.s_stop[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_shortstop_0", &s)) strncpy (bl.s_shortstop[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_shortstop_1", &s)) strncpy (bl.s_shortstop[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("secondblock", &s)) strncpy (bl.secondblock, s.c_str(), REFERENCENAME_LEN);
printf ("%s:%d block: %s flags: %d\n", __FILE__, __LINE__, bl.name, bl.flags);
return bl;
};
@ -208,301 +150,3 @@ int Blocks::Delete(string name) {
};
//
// thread will not be locked..
int Blocks::SetOff(string blname) {
Block *bl = NULL;
JSONParse jp;
Lock();
if ((bl = FindBlock(blname)) != NULL) {
changed = 1;
bl->flags |= BLOCK_F_OFF;
debug (0, "Blocks::SetOff block %s", bl->name);
jp.AddObject("block",_GetJSON(bl));
if(network) network->ChangeListPushToAll(jp.ToString());
UnLock();
return 1;
}
UnLock();
return 1;
};
int Blocks::IsOff(string blname) {
// return -1 if not found, 0 on no lock, 1 on lock
Block *bl = NULL;
int res = -1;
Lock();
if ((bl = FindBlock(blname)) != NULL) {
if (bl->flags & BLOCK_F_OFF) res = 1;
else res = 0;
}
UnLock();
return res;
};
int Blocks::SetLockedby (string blname, string lockedby, int lock_onoff) {
// return -1 if not found, 0 on no lock, 1 on lock
Block *bl = NULL;
JSONParse jp;
int res = -1;
int x, y, cnt;
debug (0, "Blocks::SetLockedby block:'%s' locked for '%s' locked:%d", blname.c_str(), lockedby.c_str(), lock_onoff);
Lock();
if ((bl = FindBlock(blname)) != NULL) {
if (lockedby.compare (bl->lockedby) == 0 || bl->lockedby[0] == 0) {
if (lock_onoff) strncpy (bl->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
else bl->lockedby[0] = 0;
jp.AddObject("block",_GetJSON(bl));
if(network) network->ChangeListPushToAll(jp.ToString());
x = -1; y = -1;
cnt = 0;
while (server->railways.FindReference(&x, &y, blname, (cnt++))) {
server->railways.SetLockedby(x, y, lockedby, lock_onoff);
}
res = 1;
}
else {
debug (0, "Blocks::SetLockedby could not set block '%s' for '%s'. Is used by '%s'.", blname.c_str(),lockedby.c_str(), bl->lockedby);
res = 0;
}
}
else {
debug (0, "Blocks::SetLockedby could not find block '%s'.", blname.c_str());
}
UnLock();
return res;
};
string Blocks::GetLockedby (string blname) {
Block *bl = NULL;
string lb;
Lock();
if ((bl = FindBlock(blname)) != NULL) {
lb = bl->lockedby;
UnLock();
return lb;
}
UnLock();
return "";
};
string Blocks::GetSecondBlock(string block) {
Block *bl = NULL;
string sb;
Lock();
if ((bl = FindBlock(block)) != NULL) {
sb = bl->secondblock;
UnLock();
return sb;
}
UnLock();
return "";
}
Block* Blocks::FindBlock(string name) {
Block *bl = NULL;
if (last_blockidx >= 0 && last_blockidx < max)
if (name.compare (blocks[last_blockidx].name) == 0)
return &blocks[last_blockidx];
for (last_blockidx = 0; last_blockidx < max; last_blockidx++) {
if (name.compare (blocks[last_blockidx].name) == 0)
return &blocks[last_blockidx];
}
return bl;
};
int Blocks::Clear(string name) {
Block *bl = NULL;
Lock();
if ((bl = FindBlock(name)) != NULL) {
changed = 1;
bl->flags &= ~BLOCK_F_OFF;
printf ("%s:%d clear block %s off", __FILE__, __LINE__, bl->name);
UnLock();
return 1;
}
UnLock();
return 0;
};
void Blocks::ClearLockedby(string name) {
int i;
JSONParse jp;
Lock();
for (i = 0; i < max; i++) {
if (name.compare(blocks[i].lockedby) == 0) {
blocks[i].lockedby[0] = 0;
changed = 1;
jp.AddObject("block",_GetJSON(i));
if(network) network->ChangeListPushToAll(jp.ToString());
}
}
UnLock();
};
int Blocks::GetFlags (string blname) {
int res = 0;
int i;
JSONParse jp;
Lock();
for (i = 0; i < max; i++) if (blname.compare(blocks[i].name) == 0) {
res = blocks[i].flags;
}
UnLock();
return res;
};
/*
* return a pointer to the blockdata in case of split blocks also return the second block
*/
int Blocks::GetBlocksPtr (string blname, Block **b1, Block **b2) {
int i;
(*b1) = NULL;
(*b2) = NULL;
for (i = 0; i < max; i++) if (blname.compare(blocks[i].name) == 0) {
(*b1) = &blocks[i];
}
if ((*b1) == NULL) {
debug (0, "Blocks::%s Could not find block: %s", __FUNCTION__, blname.c_str());
return 0;
}
if ((*b1)->flags & BLOCK_F_SPLIT) {
for (i = 0; i < max; i++) if (strcmp ((*b1)->secondblock, blocks[i].name) == 0) {
(*b2) = &blocks[i];
}
if ((*b2) == NULL) {
debug (0, "Blocks::%s Could not find second block: %s", __FUNCTION__, (*b1)->secondblock);
return 0;
}
}
return 1;
}
string Blocks::GetSensorEnter (int direction, string blname, int locoflags) {
string res = "";
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_enter[direction];
else res = b2->s_enter[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_enter[direction];
else res = b1->s_enter[direction];
}
}
if (res.length() == 0) {
res = b1->s_enter[direction];
}
UnLock();
return res;
};
string Blocks::GetSensorSlow (int direction, string blname, int locoflags) {
string res = "";
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_slow[direction];
else res = b1->s_slow[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_slow[direction];
else res = b2->s_slow[direction];
}
}
if (res.length() == 0) {
res = b1->s_slow[direction];
}
if (res.length() == 0) {
res = b1->s_enter[direction];
}
UnLock();
return res;
};
string Blocks::GetSensorStop (int direction, string blname, int locoflags) {
string res = "";
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if ((locoflags & LOCO_F_SHORTTRAIN) && b1->s_shortstop[direction][0] != 0)
res = b1->s_shortstop[direction];
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_stop[direction];
else res = b1->s_stop[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_stop[direction];
else res = b2->s_stop[direction];
}
}
if (res.length() == 0) {
res = b1->s_stop[direction];
}
UnLock();
return res;
};

@ -2,58 +2,14 @@
#ifndef _BLOCK_H_
#define _BLOCK_H_
#include <list>
#include <string>
#include <string.h>
using namespace std;
#include "modelbahn.h"
#include "server.h"
#define BLOCK_F_OFF 0x0001
#define BLOCK_F_SPLIT 0x0002 // is this a split block? only works for short
#define BLOCK_F_SPLITPOS 0x0004 // is this a split block? only works for short
#define BLOCK_F_SHORT 0x0010
#define BLOCK_F_ENDSTATION 0x0040
#define BLOCK_F_STATION 0x0080
#define BLOCK_F_SPEEDLIMIT 0x0100
#define BLOCK_F_ONLYCARGO 0x0200
#define BLOCK_F_ONLYPASSENGER 0x0400
/*
* FIXME: long trains on split blocks
* FIXME: sample how to set up positive entry side
*
* Dirction Pos: from Left to Right Neg: from Right to Left
* Dirction Pos: from Top to Bottom Neg: from Bottom to Top
*
* pos SPLIT BLOCK neg SPLIT BLOCK
* F_SPLIT | F_SPLITPOS F_SPLIT
* >----o-------------o------o-------------o---> entry direction
*
* ^ ^ ^
* | | |
* s_enter[0] s_shortstop[0] | positive_block
* s_stop[0] negative block
*/
#define BLOCKF_SHORTTRAIN 0x0001
struct s_Block {
char name[REFERENCENAME_LEN];
// default sensors [0].. positive side [1] negative side
char s_enter[2][REFERENCENAME_LEN];
char s_slow[2][REFERENCENAME_LEN];
char s_stop[2][REFERENCENAME_LEN];
char s_shortstop[2][REFERENCENAME_LEN];
char secondblock[REFERENCENAME_LEN]; // short two blocks segment.
int flags;
char lockedby[REFERENCENAME_LEN]; // element locked by locreference (only set by server, not by JSON/Webinterface)
} typedef Block;
class Blocks {
@ -67,12 +23,7 @@ class Blocks {
int UnLock();
// not thread safe
JSONParse _GetJSON(Block *bl);
JSONParse _GetJSON(int idx) { return _GetJSON(&blocks[idx]); };
int last_blockidx; // to speed up things
Block* FindBlock(string name);
int GetBlocksPtr(string blname, Block **b1, Block **b2);
JSONParse _GetJSON(int idx);
public:
Blocks();
~Blocks();
@ -86,21 +37,6 @@ class Blocks {
JSONParse GetJSON(string name);
void GetJSONAll(JSONParse *json);
Block GetBlockFromJSON(JSONParse *j);
int SetOff(string blname);
int IsOff(string blname);
string GetSensorEnter (int direction, string blname, int locoflags);
string GetSensorSlow (int direction, string blname, int locoflags);
string GetSensorStop (int direction, string blname, int locoflags);
int GetFlags (string blname);
string GetSecondBlock(string block);
int SetLockedby (string blname, string lockedby, int lock_onoff);
string GetLockedby (string blname);
void ClearLockedby(string name);
int Clear(string name);
};
#endif

@ -2,49 +2,32 @@
// #define _GNU_SOURCE /* See feature_test_macros(7) */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/time.h>
#include "modelbahn.h"
#define DEBUG_FILE "/tmp/modelbahn-server.log"
#define LEN_TEXT 256
int _debuglevel = 0xff;
pid_t gettid();
void debug (int type, char *fmt,...) {
va_list args;
char texttime[LEN_TEXT];
char text1[DEBUG_TEXT1LEN];
char text2[DEBUG_TEXT2LEN];
pid_t pid = gettid();
int tms;
struct timeval tv;
struct tm tmp;
struct tm *tmptr = NULL;
va_start (args, fmt);
vsnprintf (text1, (DEBUG_TEXT1LEN-1), fmt, args);
va_end (args);
texttime[0] = 0;
text1[DEBUG_TEXT1LEN-1] = 0;
text2[DEBUG_TEXT2LEN-1] = 0;
gettimeofday (&tv, NULL);
tmptr = localtime_r(&tv.tv_sec, &tmp);
if (tmptr != NULL)
strftime(texttime, LEN_TEXT, "%H:%M:%S", &tmp);
if (type > 0) snprintf (text2, DEBUG_TEXT2LEN-1, "(%d, %s.%03d) %d : %s", pid, texttime, tv.tv_usec/1000, type, text1);
else snprintf (text2, DEBUG_TEXT2LEN-1, "(%d, %s.%03d) : %s", pid, texttime, tv.tv_usec/1000, text1);
if (type > 0) snprintf (text2, DEBUG_TEXT2LEN-1, "(%d)%d: %s", pid, type, text1);
else snprintf (text2, DEBUG_TEXT2LEN-1, "(%d) %s", pid, text1);
if (type == 0 || (type & _debuglevel) != 0) {
FILE *f;

@ -33,14 +33,11 @@ static unsigned char RX_RMBUS_DATACHANGED[] { 0x0F, 0x00, 0x80, 0x00 };
#define Z21_IDX_SETTURNOUT_CHK 8
InterfaceZ21::InterfaceZ21 () {
debug (DEBUG_INFO | DEBUG_IFACE, "InterfaceZ21:%s", __FUNCTION__);
status_connected = false;
status_poweron = false;
status_programmingmode = false;
status_shortcircuit = false;
status_emergencystop = false;
timer_start(&turnouttimeout);
send_logon = false;
@ -48,6 +45,7 @@ InterfaceZ21::InterfaceZ21 () {
rmsensorinit = 0;
serial = "";
hostname = "";
timeout = time(NULL);
rmgetdatatimeout = time(NULL) - INTF_Z21_RMGETDATA_TIMEOUT;
};
@ -57,11 +55,11 @@ InterfaceZ21::~InterfaceZ21() {
};
void InterfaceZ21::Connect () {
debug (DEBUG_INFO | DEBUG_IFACE, "InterfaceZ21: Connect %s to: %s", name, host);
void InterfaceZ21::Connect (string destination) {
debug (DEBUG_INFO | DEBUG_IFACE, "%s:%d Connect to: %s", __FILE__, __LINE__, destination.c_str());
if (status_connected) Disconnect();
hostname = destination;
if (udp.Listen(0) == 0) {
debug (DEBUG_ERROR | DEBUG_IFACE, "%s:%d Error could not bind UDP socket (%s)",
@ -99,18 +97,12 @@ void InterfaceZ21::Disconnect() {
//
// check if we are connected and for timeouts.
// read and go through incoming data
int InterfaceZ21::Loop() {
int InterfaceZ21::Loop(string interfacename) {
time_t curtime = time(NULL);
string source;
int inlen;
int i;
// debug (DEBUG_INFO | DEBUG_IFACE, "* InterfaceZ21 (%s) Loop", name);
flags &= ~(INTF_F_CONNECTED | INTF_F_POWER | INTF_F_STOP | INTF_F_SHORT_CIRCUIT | INTF_F_PROGRAMMING);
if (needs_update) {
needs_update = 0;
}
int update = false;
if (status_connected) {
//
@ -118,14 +110,14 @@ int InterfaceZ21::Loop() {
if ((timeout + 2 * INTF_Z21_TIMEOUT) < curtime) {
debug (DEBUG_ERROR | DEBUG_IFACE, "%s:%d connection timed out (%d)", __FILE__, __LINE__, curtime-(timeout + 2 * INTF_Z21_TIMEOUT));
Disconnect();
needs_update = true;
update = true;
}
else if (send_logon == false && (timeout + INTF_Z21_TIMEOUT) < curtime) {
send_logon = true;
send_GET_SERIAL_NUMBER();
send_SET_BROADCASTFLAGS();
timeout = time(NULL);
needs_update = true;
update = true;
}
//
@ -144,7 +136,7 @@ int InterfaceZ21::Loop() {
if ((inlen = udp.ReadTimeout(&source, inbuffer, INTF_Z21_INBUFFER, 10)) > 0) {
//
// got some data
debug (DEBUG_INFO | DEBUG_IFACE, "%s:%d [%s] got some data.", __FILE__, __LINE__, name);
//
// check for LAN_SYSTEMSTATE_DATACHANGED
if (memcmp (inbuffer, RX_GET_SERIAL_NUMBER, sizeof(RX_GET_SERIAL_NUMBER)) == 0) {
@ -157,13 +149,13 @@ int InterfaceZ21::Loop() {
if (memcmp (inbuffer, RX_X_GET_TURNOUT_INFO, sizeof(RX_X_GET_TURNOUT_INFO)) == 0) {
// got turnout information
int addr = 0;
addr = ((unsigned char)inbuffer[Z21_IDX_SETTURNOUT_ADRH] << 8) + (unsigned char)inbuffer[Z21_IDX_SETTURNOUT_ADRL];
debug (0, "%s:%d Interface-Z21: TurnoutInformation Addr:%d", __FILE__, __LINE__, addr);
if (inbuffer[Z21_IDX_SETTURNOUT_MODE] == 2)
server->TurnoutAddrMode(name, addr, 1);
server->TurnoutAddrMode(interfacename, addr, 1);
else if (inbuffer[Z21_IDX_SETTURNOUT_MODE] == 1)
server->TurnoutAddrMode(name, addr, 0);
server->TurnoutAddrMode(interfacename, addr, 0);
}
@ -174,14 +166,20 @@ int InterfaceZ21::Loop() {
int cs = (unsigned char) inbuffer[16];
int csex = (unsigned char) inbuffer[17];
bool old_poweron = status_poweron;
bool old_shortcircuit = status_shortcircuit;
bool old_programmingmode = status_programmingmode;
bool old_connected = status_connected;
bool old_emergencystop = status_emergencystop;
status_emergencystop = (cs & INTF_Z21_CS_EmergencyStop);
status_poweron = (cs & INTF_Z21_CS_TrackVoltageOff);
status_shortcircuit = (cs & INTF_Z21_CS_ShortCircuit);
status_programmingmode = (cs & INTF_Z21_CS_ProgModeActive);
debug (0, "%s:%d Name:%s cs:%d csex:%d", __FILE__, __LINE__, name, cs, csex);
debug (0, "%s:%d cs:%d csex:%d", __FILE__, __LINE__, cs, csex);
needs_update = true;
update = true;
//if ( old_poweron != status_poweron ||
// old_shortcircuit != status_shortcircuit ||
// old_programmingmode != status_programmingmode ||
@ -215,10 +213,10 @@ int InterfaceZ21::Loop() {
loconet_map[inloc].addr = loconet_last.addr;
}
debug (0, "%s:%d Loc:%d Speed:%d", __FILE__, __LINE__, loconet_map[inloc].addr, inspeed);
debug (0, "%s:%d Loc:%d Speed:%d\n", __FILE__, __LINE__, loconet_map[inloc].addr, inspeed);
if (loconet_map[inloc].addr > 0) {
int speed = inspeed;
server->LocomotiveAddrSpeed(name, loconet_map[inloc].addr, speed);
server->LocomotiveAddrSpeed(interfacename, loconet_map[inloc].addr, speed);
}
}
loconet_last.addr = 0;
@ -232,14 +230,8 @@ int InterfaceZ21::Loop() {
if (inloc >= 0 && inloc <= INTF_Z21_LOCONET_MAXADDR) {
if (loconet_last.addr) loconet_map[inloc] = loconet_last;
debug (0, "%s:%d Loc:%d Function:%d", __FILE__, __LINE__, loconet_map[inloc].addr, infunc);
}
debug (0, "%s:%d Loc:%d Function:%d", __FILE__, __LINE__, loconet_map[inloc].addr, infunc);
if (loconet_map[inloc].addr > 0) {
server->LocomotiveAddrFunction(name, loconet_map[inloc].addr, infunc);
debug (0, "%s:%d Loc:%d Function:%d\n", __FILE__, __LINE__, loconet_map[inloc].addr, infunc);
}
loconet_last.addr = 0;
}
}
@ -248,9 +240,9 @@ int InterfaceZ21::Loop() {
// check for LAM_RMBUS_DATACHANGED
else if (memcmp (inbuffer, RX_RMBUS_DATACHANGED, sizeof(RX_RMBUS_DATACHANGED)) == 0) {
int group = (unsigned char)inbuffer[4];
int idx;
int idx, bit;
printf ("LAN_RMBUS_DATA_CHANGE[%s] ", name);
printf ("LAN_RMBUS_DATA_CHANGE[%s] ", interfacename.c_str());
for (idx = 0; idx < INTF_Z21_RMSENSOR_BYTES * INTF_Z21_RMSENSOR_GROUPS; idx++) {
printf ("%x ", (unsigned char) inbuffer[4+idx]);
}
@ -267,9 +259,9 @@ int InterfaceZ21::Loop() {
for (idx = 0; idx < INTF_Z21_RMSENSOR_GROUPS*INTF_Z21_RMSENSOR_BYTES; idx++) {
if (rmsold[idx]^rmsensors[idx]) {
for (i = 0; i < 8; i++) if (rmsensorinit || (rmsold[idx] & 1 << i) != (rmsensors[idx] & 1 << i)) {
debug (0, "Sendor Data Changed: %s[%d]", name, idx*8+i);
if (rmsensors[idx] & 1 << i) server->SensorAddrChange(name, idx*8+i, 1);
else server->SensorAddrChange(name, idx*8+i, 0);
debug (0, "Sendor Data Changed: %s[%d]", interfacename.c_str(), idx*8+i);
if (rmsensors[idx] & 1 << i) server->SensorAddrChange(interfacename, idx*8+i, 1);
else server->SensorAddrChange(interfacename, idx*8+i, 0);
}
}
}
@ -278,7 +270,7 @@ int InterfaceZ21::Loop() {
}
else {
printf ("InterfaceZ21(%s) Got some Data:", name);
printf ("InterfaceZ21(%s) Got some Data:", interfacename.c_str());
for (i = 0; i < inlen; i++) {
int z = (unsigned char) inbuffer[i];
printf ("%02x:", z);
@ -294,12 +286,7 @@ int InterfaceZ21::Loop() {
}
}
if (IsConnected()) flags |= INTF_F_CONNECTED;
if (IsPoweron()) flags |= INTF_F_POWER;
if (IsEmergencyStop()) flags |= INTF_F_STOP;
if (IsSortCircuit()) flags |= INTF_F_SHORT_CIRCUIT;
return needs_update;
return update;
};
@ -307,14 +294,14 @@ int InterfaceZ21::Loop() {
// send_SET_BROADCASTFLAGS();
void InterfaceZ21::send_SET_BROADCASTFLAGS() {
unsigned char buffer[] = { 0x08, 0x00, 0x50, 0x00, 0x0F, 0x01, 0x00, 0x03 };
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
}
//
// send_GET_SERIAL_NUMBER
void InterfaceZ21::send_GET_SERIAL_NUMBER() {
unsigned char buffer[] = { 0x04, 0x00, 0x10, 0x00 };
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
}
@ -324,7 +311,7 @@ void InterfaceZ21::send_RM_GETDATA(int group) {
unsigned char buffer[] = { 0x05, 0x00, 0x81, 0x00, 0x00 };
if (group < INTF_Z21_RMSENSOR_GROUPS) {
buffer[4] = (unsigned char)group;
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
}
}
@ -335,7 +322,7 @@ void InterfaceZ21::send_LOGOFF() {
if (status_connected == false) return;
unsigned char buffer[] = { 0x04, 0x00, 0x30, 0x00 };
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
}
@ -354,8 +341,8 @@ void InterfaceZ21::SetLocoSpeed(Locomotive *l, int step) {
else if (step > 0) {
l->flags &= ~LOCO_F_REVERSE;
}
if (l->flags & LOCO_F_REVERSE) buffer[Z21_IDX_SETLOCO_DRIVE_STEP] = 0x00;
else buffer[Z21_IDX_SETLOCO_DRIVE_STEP] = 0x80;
if (l->flags & LOCO_F_REVERSE) buffer[Z21_IDX_SETLOCO_DRIVE_STEP] = 0x80;
else buffer[Z21_IDX_SETLOCO_DRIVE_STEP] = 0x00;
//
// setup loc addr
@ -366,12 +353,12 @@ void InterfaceZ21::SetLocoSpeed(Locomotive *l, int step) {
//
// setup steps and selected step
if (l->stepcode == LOCO_INT_DCC14) {
if (l->steps <= 14) {
buffer[Z21_IDX_SETLOCO_DRIVE_SFMT] = 0x10;
if (step == 0) buffer[Z21_IDX_SETLOCO_DRIVE_STEP] |= 0;
else buffer[Z21_IDX_SETLOCO_DRIVE_STEP] |= (abs(step)+1);
}
else if (l->stepcode == LOCO_INT_DCC28) {
else if (l->steps <= 28) {
buffer[Z21_IDX_SETLOCO_DRIVE_SFMT] = 0x12;
if (step == 0) buffer[Z21_IDX_SETLOCO_DRIVE_STEP] |= 0;
else {
@ -379,7 +366,7 @@ void InterfaceZ21::SetLocoSpeed(Locomotive *l, int step) {
if (abs(step) & 0x01) buffer[Z21_IDX_SETLOCO_DRIVE_STEP] |= 0x10;
}
}
else if (l->stepcode == LOCO_INT_DCC128) {
else if (l->steps <= 128) {
buffer[Z21_IDX_SETLOCO_DRIVE_SFMT] = 0x13;
if (step == 0) buffer[Z21_IDX_SETLOCO_DRIVE_STEP] |= 0;
else buffer[Z21_IDX_SETLOCO_DRIVE_STEP] |= (abs(step)+1);
@ -387,21 +374,21 @@ void InterfaceZ21::SetLocoSpeed(Locomotive *l, int step) {
//
// XOR Byte
for (int i = 4; i < (int) sizeof (buffer)-1; i++)
for (int i = 4; i < sizeof (buffer)-1; i++)
buffer[Z21_IDX_SETLOCO_DRIVE_CHK] = (unsigned char)buffer[Z21_IDX_SETLOCO_DRIVE_CHK] xor (unsigned char)buffer[i];
printf ("Send Data:");
for (int i = 0; i < (int)sizeof (buffer); i++) {
for (int i = 0; i < sizeof (buffer); i++) {
int z = (unsigned char) buffer[i];
printf ("%02x:", z);
}
printf ("\n");
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
loconet_last.addr = l->addr;
loconet_last.dir = l->flags & LOCO_F_REVERSE;
loconet_last.speed = l->speed;
loconet_last.maxspeed = l->vmax;
loconet_last.stepcode = l->stepcode;
loconet_last.steps = l->steps;
};
@ -414,18 +401,10 @@ void InterfaceZ21::SetLocoFunction(Locomotive *l, int func, int value) {
//
// Set Turnout
void InterfaceZ21::SetTurnout(Turnout *t, int activate, int outputactive) {
void InterfaceZ21::SetTurnout(Turnout *t, int activate, int motoractive) {
unsigned char buffer[] = { 0x09, 0x00, 0x40, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00 };
debug (DEBUG_INFO | DEBUG_IFACE, "InterfaceZ21 (%s) SetTurnout Addr:%d Acitve:%d Output:%d", name,
t->addr, activate, outputactive);
//
//
if (outputactive == 1 && timer_get(&turnouttimeout) < 100) {
debug (0, "%s:%d Interface need to wait between two turnout commands", __FILE__, __LINE__);
return;
}
timer_start(&turnouttimeout);
debug (0, "%s:%d InterfaceZ21::SetTurnout (a:%d, m:%d)", __FILE__, __LINE__, activate, motoractive);
//
// setup turnout addr
@ -436,21 +415,20 @@ void InterfaceZ21::SetTurnout(Turnout *t, int activate, int outputactive) {
// setup steps and selected step
buffer[Z21_IDX_SETTURNOUT_MODE] = 0x80;
if (activate) buffer[Z21_IDX_SETTURNOUT_MODE] |= 1;
if (outputactive) buffer[Z21_IDX_SETTURNOUT_MODE] |= 8;
if (motoractive) buffer[Z21_IDX_SETTURNOUT_MODE] |= 8;
//
// XOR Byte
for (int i = 4; i < (int) sizeof (buffer)-1; i++)
for (int i = 4; i < sizeof (buffer)-1; i++)
buffer[Z21_IDX_SETTURNOUT_CHK] = (unsigned char)buffer[Z21_IDX_SETTURNOUT_CHK] xor (unsigned char)buffer[i];
udp.Write(host, (char*)buffer, sizeof (buffer));
//
// set the output flag
if (outputactive) t->flags |= TURNOUT_F_ACTIVE;
else t->flags &= ~TURNOUT_F_ACTIVE;
gettimeofday (&t->activatetime, NULL);
printf ("Send Data:");
for (int i = 0; i < sizeof (buffer); i++) {
int z = (unsigned char) buffer[i];
printf ("%02x:", z);
}
printf ("\n");
udp.Write(hostname, (char*)buffer, sizeof (buffer));
};
@ -459,11 +437,11 @@ void InterfaceZ21::SetTurnout(Turnout *t, int activate, int outputactive) {
// send_X_SET_TRACK_POWER_ON(); send_X_SET_TRACK_POWER_ON();
void InterfaceZ21::PowerOnOff(int onoff) {
if (status_connected == false) return;
debug (DEBUG_INFO | DEBUG_IFACE, "InterfaceZ21::PowerOnOff onoff:%d", onoff);
if (onoff) {
udp.Write(host, (char*)TX_X_SET_TRACK_POWER_ON, sizeof (TX_X_SET_TRACK_POWER_ON));
udp.Write(hostname, (char*)TX_X_SET_TRACK_POWER_ON, sizeof (TX_X_SET_TRACK_POWER_ON));
}
else {
udp.Write(host, (char*)TX_X_SET_TRACK_POWER_OFF, sizeof (TX_X_SET_TRACK_POWER_OFF));
udp.Write(hostname, (char*)TX_X_SET_TRACK_POWER_OFF, sizeof (TX_X_SET_TRACK_POWER_OFF));
}
};

@ -15,21 +15,22 @@
#define INTF_Z21_CS_ShortCircuit 0x04
#define INTF_Z21_CS_ProgModeActive 0x20
#define INTF_Z21_LOCONET_MAXADDR 255
#define INTF_Z21_LOCONET_MAXADDR 255
#define INTF_Z21_RMSENSOR_GROUPS 2
#define INTF_Z21_RMSENSOR_BYTES 10
#define INTF_Z21_RMGETDATA_TIMEOUT 30
#define INTF_Z21_RMSENSOR_BYTES 10
#define INTF_Z21_RMGETDATA_TIMEOUT 30
struct s_loconet_map{
int addr;
int dir;
int stepcode;
int steps;
int speed;
int maxspeed;
};
class InterfaceZ21: public Interface {
class InterfaceZ21 {
private:
string hostname;
string serial;
char inbuffer[INTF_Z21_INBUFFER];
struct s_loconet_map loconet_map[INTF_Z21_LOCONET_MAXADDR];
@ -38,7 +39,6 @@ class InterfaceZ21: public Interface {
UDP udp;
time_t timeout;
time_t rmgetdatatimeout;
struct timeval turnouttimeout;
bool send_logon;
bool status_poweron;
@ -61,7 +61,7 @@ class InterfaceZ21: public Interface {
InterfaceZ21();
~InterfaceZ21();
void Connect();
void Connect(string destination);
void Disconnect();
bool IsConnected() { return status_connected; };
@ -70,11 +70,11 @@ class InterfaceZ21: public Interface {
bool IsProgramminnMode() { return status_programmingmode; };
bool IsEmergencyStop() { return status_emergencystop; };
int Loop();
int Loop(string interfacename);
void PowerOnOff(int onoff);
void SetLocoSpeed(Locomotive *l, int step);
void SetLocoFunction(Locomotive *l, int func, int value);
void SetTurnout(Turnout *t, int activate, int outputactive);
void SetTurnout(Turnout *t, int activate, int motoractive);
};

@ -10,8 +10,6 @@
// **************************************************************************
Interface::Interface() {
debug (DEBUG_INFO | DEBUG_IFACE, "Interface:%s", __FUNCTION__);
name[0] = 0;
host[0] = 0;
flags = 0;
@ -25,28 +23,50 @@ 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:
* this function will check if the interface has not set any output within the past 100ms. For this we
* will save the current time in the value turnouttime.
*/
void Interface::SetTurnout(Turnout *t, int active, int outputactive) {
JSONParse jp;
//
// 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;
}
debug (DEBUG_INFO | DEBUG_IFACE, "%s:%d Interface (%s) SetTurnout Addr:%d Acitve:%d Output:%d", __FILE__, __LINE__, name,
t->addr, active, outputactive);
//
// 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);
};
//
@ -54,62 +74,319 @@ void Interface::SetTurnout(Turnout *t, int active, int outputactive) {
//
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;
}
};
//
// if update is needed return 1
//
int Interface::Loop() {
int ret = 0;
// debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) Loop", name);
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;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsConnected", name);
switch (type) {
case INTF_T_Z21: ret = intz21.IsConnected(); break;
default: break;
}
return ret;
}
bool Interface::IsPoweron() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsPoweron", name);
return ret;
}
switch (type) {
case 1: ret = intz21.IsPoweron(); break;
default: break;
}
bool Interface::IsSortCircuit() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsSortCircuit", name);
return ret;
}
bool Interface::IsProgramminnMode() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsProgramminnMode", name);
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;
}
bool Interface::IsEmergencyStop() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsEmergencyStop", name);
return ret;
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());
}
}
};

@ -6,6 +6,7 @@
#include "server.h"
#include "UDPTCPNetwork.h"
#include "json.h"
#include "interface-z21.h"
#define INTF_F_CONNECTED 0x0001
#define INTF_F_POWER 0x0002
@ -14,34 +15,72 @@
#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:
public:
InterfaceZ21 intz21;
bool needs_update;
public:
char name[REFERENCENAME_LEN];
char host[NET_HOSTLEN];
int flags;
int type;
Interface();
virtual ~Interface();
~Interface();
void Connect();
void Disconnect();
void PowerOnOff(int onoff);
void SetLocoSpeed(Locomotive *l, int step);
void SetLocoFunction(Locomotive *l, int func, int value);
void SetTurnout(Turnout *t, int active, int motoractive);
bool IsConnected();
bool IsPoweron();
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; };
virtual void Connect();
virtual void Disconnect();
int Change(Interface *iface);
int Delete(string name);
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);
JSONParse GetJSON(string name);
void GetJSONAll(JSONParse *json);
Interface GetInterfaceFromJSON(JSONParse *j);
virtual bool IsConnected();
virtual bool IsPoweron();
virtual bool IsSortCircuit();
virtual bool IsProgramminnMode();
virtual bool IsEmergencyStop();
//
//
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 motoractive);
virtual int Loop();
void Loop();
};
#endif

@ -1,293 +0,0 @@
#include <string>
#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;
pthread_mutex_init(&mtx, NULL);
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;
printf ("Interface Type:%d\n", iface->type);
LockThread();
for (i = 0; i < max; i++) {
if (interfaces[i] != NULL) {
// found element
if (strncmp(interfaces[i]->name, iface->name, REFERENCENAME_LEN) == 0) {
delete interfaces[i];
interfaces[i] = NULL;
ifree = i;
break;
}
}
else if (ifree == -1) ifree = i;
}
// element found or we need to add the 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);
//
// if the interfacename is debug ... simulate a change in the turnout
//
if (strncmp(t->ifname, "DEBUG", REFERENCENAME_LEN) == 0) {
if (active) t->flags |= TURNOUT_F_ACTIVE;
else t->flags &= ~TURNOUT_F_ACTIVE;
server->TurnoutAddrMode(t->ifname, t->addr, active);
}
else {
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;
debug (0, "Interfaces::SetLocoSpeed Loco:'%s' Speed:%d", l->name, speed);
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;
debug (0, "Interfaces::SetLocoFunction Loco:'%s' Function:%d Value:%d", l->name, func, value);
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());
}
}
};

@ -1,61 +0,0 @@
#ifndef _INTERFACES_H_
#define _INTERFACES_H_
#include "modelbahn.h"
#include "server.h"
#include "UDPTCPNetwork.h"
#include "json.h"
#include "interface.h"
#include "interfaces.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
enum {
INTF_T_OFF_UNKNOWN = 0,
INTF_T_Z21,
INTF_T_MAX
};
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

@ -3,9 +3,6 @@
#include <string>
#include <string.h>
using namespace std;
#include "debug.h"
#include "json.h"
@ -52,7 +49,7 @@ int JSONParse::Set(string json) {
Clear();
// find start and read until end
for (step = STEP_NONE, i = 0, ignorenext = false; i < (int) json.length(); i++) {
for (step = STEP_NONE, i = 0, ignorenext = false; i < json.length(); i++) {
// need to copy next character
// debug (0, "JSONParse: step:%d i:%d name:'%s' value:'%s'", step, i, jelement.name.c_str(), jelement.value.c_str());
if (ignorenext) {
@ -249,7 +246,7 @@ int JSONParse::GetIdx(string src, int idx, string *dest) {
// printf("\n***************************************idx:%d\n", idx);
for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0;
for (i = 0; i < (int) src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
for (i = 0; i < src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
// printf ("i:%d rcnt:%d['%c'] cnt:%d char:'%c' ous:'%s'\n",
// i, rcnt, recursive[rcnt], cnt, src[i], dest->c_str());
if (src[i] == '[') {
@ -466,6 +463,9 @@ string JSONElement::GetString () {
if (value.length()==0) {
output += "\"" + name + "\" : \"\"";
}
// FIXME: we have to define all strings are saved here without ""
// will be set up in the future
// WORKAROUND for empty strings
else if (value[0] != '"') {
output += "\"" + name + "\" : \"" + value + "\"";
}
@ -478,6 +478,7 @@ string JSONElement::GetString () {
if (value.length()==0) {
output += "\"" + name + "\" : []";
}
// WORKAROUND for arrays without []
else if (value[0] != '[') {
output += "\"" + name + "\" : [" + value + "]";
}

File diff suppressed because it is too large Load Diff

@ -5,71 +5,23 @@
#include "modelbahn.h"
#include "server.h"
#define LOCO_F_REVERSE 0x0001
#define LOCO_F_CARGO 0x0010
#define LOCO_F_CANREVERSE 0x0020
#define LOCO_F_SHORTTRAIN 0x0040
#define LOCO_F_AUTO 0x0100
#define LOCO_F_AUTOSHED 0x0200
#define LOCO_F_AUTORANDOM 0x0400
#define LOCO_F_AUTOSTOP 0x0800
#define LOCO_TO_TURNOUT (50+TURNOUT_DEFAULT_ACTIVETIMEOUT)
#define LOCO_TO_TRYAGAIN (1000)
#define WAYDATA_LEN (16*REFERENCENAME_LEN)
enum {
LOCO_INT_UNDEF = 0,
LOCO_INT_DCC14,
LOCO_INT_DCC28,
LOCO_INT_DCC128
};
enum {
LOCO_OR_NOTHING = 0,
LOCO_OR_SEARCH, // search way (to next block and lock way)
LOCO_OR_PREPARE, // switch turnouts right way (one every 100ms)
// if no turnout has to been set, continue
LOCO_OR_ONTHEWAY, // locomotive is on the way // maybe prepare next block?
// ASSIGN -> PREV, NEXT -> ASSIGN, NEXT <- (empty)
// propabely searching next block (if DEST is set)?
LOCO_OR_ENTERBLOCKNEXT, // got new block ready?
LOCO_OR_ENTERBLOCKSTOP, // got new block ready?
// if NEXT is empty and way not AutoPrepareWay not finished... slow down
LOCO_OR_STOPWAIT // stopping
};
#define LOCO_F_REVERSE 0x0001
struct s_Locomotive {
char name[REFERENCENAME_LEN]; // name
char ifname[REFERENCENAME_LEN]; // ref. of interface
int addr; // address on bus
int stepcode; // stepcoding LOCO_INT_DCC...
int flags; // flags
int vmin; // speed - below this we always set 0
int vslow; // speed - slow entry in trainstation
int vmid; // speed - for normal trains (max for cargo trains, on automode)
int vfast; // speed - for normal trains
int vmax; // speed - maximum speed
char schedway[WAYDATA_LEN]; // scheduled way W:15,B:+B17,W30,B:-B21
// dynamic data
int speed; // current speed
int64_t func; // function enabled ... light...
char blockassign[REFERENCENAME_LEN]; // currently assigned block [+BLOCKREFNAME ... -BLOCKREFNAME]
char blocknext[REFERENCENAME_LEN]; // next block to go to
char blockprev[REFERENCENAME_LEN]; // prev block (mostly assigned block
char blockdest[REFERENCENAME_LEN]; // destination block
int sched_step; // on automode this is the scheduled way step
char auto_way[WAYDATA_LEN]; // route to way "b:+blockname,t:name:0,t:name:1,b:-blockname"
char auto_wayold[WAYDATA_LEN]; // route to way "b:+blockname,t:name:0,t:name:1,b:-blockname"
int auto_onroute; // LOCO_OR_....
int auto_data; // just some data needed by some steps
struct timeval auto_timenext; // timeval of the next active step
char name[REFERENCENAME_LEN];
char ifname[REFERENCENAME_LEN];
int steps;
int speed;
int64_t func;
int flags;
int addr;
int vmin;
int vslow;
int vmid;
int vfast;
int vmax;
} typedef Locomotive;
class Locomotives {
private:
Locomotive *locomotives;
@ -82,15 +34,7 @@ class Locomotives {
// not thread safe
JSONParse _GetJSON(int idx);
int SchedulerNextStep(Locomotive *loc); // automode, calculate next step
void SendUpdate(Locomotive *loc);
int Loco_SearchAndLock(Locomotive *loco);
int Loco_PrepareWay(Locomotive *loco);
int Loco_OnRoute(Locomotive *loco);
int Loco_BlockEnterStop(Locomotive *loco);
int Loco_BlockEnterNext(Locomotive *loco);
int Loco_BlockStopWait(Locomotive *loco);
public:
Locomotives();
~Locomotives();
@ -101,24 +45,10 @@ class Locomotives {
int Change(Locomotive *loco);
int Delete(string name);
int SetSpeed(string name, int speed);
int SetReverse(string name, int reverse);
int SetFunction(string name, int func, int value);
int Reset(string name);
int SetModeMan(string name);
int SetModeAutoMan(string name);
int SetModeAuto(string name);
int SetModeAutoRand(string name);
int SetModeAutoShed(string name);
int SetSpeedFromBus (string ifname, int addr, int speed);
int SetFunctionFromBus (string ifname, int addr, int func);
int SetDestination (string name, string block, int direction);
int SetAssign (string name, string block, int direction);
int GetFlags(string name);
int AutoCheckWaySingleStep(string way, Locomotive *loc, int *data);
int Loop();
string GetName(int idx);
int SetSpeedFromBus (string name, int addr, int speed);
int SetDirectionFromBus (string name, int addr, int speed);
JSONParse GetJSON(string name);
void GetJSONAll(JSONParse *json);

@ -18,12 +18,9 @@ int running = 1;
Server *server = NULL;
Network *network = NULL;
int simulation = 0;
int main (int argc, char **argv) {
int i;
tzset(); // needed for localtime to work
int ret;
//
// setup signals
@ -40,10 +37,6 @@ int main (int argc, char **argv) {
fprintf (stderr, "%s:%d could not set signal for SIGHUB\n", __FILE__, __LINE__);
return 0;
}
if (signal(SIGUSR1, sig_int) == SIG_ERR) {
fprintf (stderr, "%s:%d could not set signal for SIGHUB\n", __FILE__, __LINE__);
return 0;
}
debug (0, "***************************************************");
@ -52,14 +45,7 @@ int main (int argc, char **argv) {
debug (0, "* *");
debug (0, "***************************************************");
debug (0, "");
for (i = 1; i < argc; i++) {
if (strcmp (argv[i], "-simulation") == 0) {
simulation = 1;
debug (0, "WARINING SIMULATION MODE ACTIVE. ALL COMMANDS WILL BE SEND");
debug (0, "TO THE INTERFACES. TURNOUT AND SENSORDATA WILL BE FORCED.");
sleep (5);
}
}
//////////////////////////////////////////////////////////////////////
//
@ -76,11 +62,9 @@ int main (int argc, char **argv) {
//
debug (0, "* application loop");
server->Start();
debug (0, "* server thread started");
network->Start();
debug (0, "* network thread started");
while (running) {
usleep (1000000);
sleep (1);
}
//////////////////////////////////////////////////////////////////////
@ -94,6 +78,7 @@ int main (int argc, char **argv) {
delete server;
debug (0, "* deleted server");
debug (0, "* application exited");
return 0;
};
@ -126,15 +111,10 @@ void timer_start(struct timeval *tv) {
};
int timer_get(struct timeval *tv) {
int timer_end(struct timeval *tv) {
struct timeval tvnow;
gettimeofday(&tvnow, NULL);
return ((tvnow.tv_sec - tv->tv_sec)*1000 + (tvnow.tv_usec - tv->tv_usec)/1000);
};
int timevaldiff (struct timeval *tv1, struct timeval *tv2) {
return ((tv1->tv_sec - tv2->tv_sec)*1000 + (tv1->tv_usec - tv2->tv_usec)/1000);
};

@ -35,14 +35,13 @@ int main (int argc, char **argv) {
//
// read data
memset (buffer, 0x0, BUFFERSIZE+1);
for (ptr = buffer, inlen = 0; inlen < BUFFERSIZE-1 && (fgets (ptr, BUFFERSIZE - inlen, stdin)) != NULL;) {
// FIXME: fgets is wrong....
for (ptr = buffer, inlen = 0; inlen < BUFFERSIZE-1 && (fgets (ptr, BUFFERSIZE - inlen, stdin)) > 0;) {
inlen = strlen (buffer);
ptr = buffer+inlen;
}
if (inlen >= BUFFERSIZE-1) fprintf (logf, "read input puffer full.\n");
fprintf (logf, "read from stdin %lu bytes\n", strlen(buffer));
// fprintf (logf, "%s\n", buffer);
fprintf (logf, "*************************************\n");
fprintf (logf, "read from stdin %d bytes\n", strlen(buffer));
//
// send data to server
@ -56,7 +55,6 @@ int main (int argc, char **argv) {
i = u.ReadTimeout(buffer, BUFFERSIZE-1, 1000);
buffer[i] = 0;
fprintf (logf, "read from server %d bytes\n", i);
fprintf (logf, "%s\n", buffer);
printf ("%s", buffer);
} while (i == BUFFERSIZE-1);
u.Close();

@ -27,15 +27,14 @@ extern int running;
extern Server *server;
extern Network *network;
extern int simulation;
//
// to measure the time in ms (used for debugging)
//
void timer_start(struct timeval *tv);
int timer_get(struct timeval *tv);
int timer_end(struct timeval *tv);
int timevaldiff (struct timeval *tv1, struct timeval *tv2);
#endif // _MODELBAHN_H_

@ -29,39 +29,40 @@ Network::Network() {
thread = 0;
sessions.clear();
thread_running = 0;
pthread_mutex_init(&mtx, NULL);
pthread_mutex_init(&mtxsessions, NULL);
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
}
Network::~Network() {
list<Session*>::iterator iter;
LockSessions();
while ((iter = sessions.begin()) != sessions.end()) {
Session *s = *iter;
sessions.remove(*iter);
delete s;
}
UnLockSessions();
Stop();
};
int Network::LockThread() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
else return 0;
}
int Network::UnLockThread() {
if (pthread_mutex_unlock(&mtx) == 0) return 1;
else return 0;
}
void Network::ThreadProcess() {
list<UNIX*>::iterator iteru;
Session *s;
UNIX *u;
int i = 0;
int timeout10s;
int cycletime_max = 0;
int cyclelooptime_max = 0;
struct timeval tv_loop, tv;
gettimeofday (&tv, NULL);
gettimeofday (&tv_loop, NULL);
timeout10s = tv.tv_sec + 10;
while (running) {
//
@ -82,21 +83,7 @@ void Network::ThreadProcess() {
}
}
gettimeofday (&tv, NULL);
i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000;
if (i > cycletime_max) cycletime_max = i;
if (i < 100 && i > 0) usleep (100000 - i*1000);
gettimeofday (&tv, NULL);
i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000;
if (i > cyclelooptime_max) cyclelooptime_max = i;
if (tv_loop.tv_sec > timeout10s) {
timeout10s = tv.tv_sec + 10;
debug (DEBUG_INFO, "Network::ThreadProcess max Cycletime: %dms Cyclelooptime:%dms", cycletime_max, cyclelooptime_max);
cycletime_max = 0;
cyclelooptime_max = 0;
}
tv_loop = tv;
usleep (100000);
}
thread_running = 0;
};
@ -135,20 +122,26 @@ void Network::Stop() {
}
void Network::ChangeListPushToAll(string changes) {
void Network::_ChangeListPushToAll(string changes) {
list<Session*>::iterator iter;
LockSessions();
for (iter = sessions.begin(); iter != sessions.end(); iter++) {
if ((*iter)->GetSessionID() > 0) (*iter)->ChangeListPush(changes);
}
UnLockSessions();
};
void Network::ChangeListPushToAll(string changes) {
LockThread();
_ChangeListPushToAll(changes);
UnLockThread();
};
int Network::ServerLoop() {
UNIX *u = NULL;
if (sockserver.IsData(10)) {
u = sockserver.Accept();
clients.push_back(u);
@ -162,14 +155,12 @@ Session *Network::GetSession(int sid) {
Session *s = NULL;
list<Session*>::iterator iter;
LockSessions();
for (iter = sessions.begin(); iter != sessions.end(); iter++) {
if ((*iter)->GetSessionID() == sid) {
s = *iter;
break;
}
}
UnLockSessions();
return s;
};
@ -177,7 +168,9 @@ Session *Network::GetSession(int sid) {
int Network::ClientLoop(UNIX *client) {
char bufferin[BUFFERSIZE];
int len, rid, sid;
char bufferout[BUFFERSIZE];
int len, i, rid, sid;
int res;
list<Session*>::iterator siter;
Session *session = NULL;
string value;
@ -194,7 +187,6 @@ int Network::ClientLoop(UNIX *client) {
JSONParse json;
JSONParse jsonout;
JSONParse jelement;
long int l;
bufferin[len] = 0; // prevent reading behind the data
@ -227,15 +219,17 @@ int Network::ClientLoop(UNIX *client) {
}
if (sid <= 0) {
int x, y;
debug (0, "* sid not set, gettin new SID");
session = new Session(rid);
sid = session->GetSessionID();
LockSessions();
LockThread();
sessions.push_back(session);
UnLockSessions();
UnLockThread();
}
else {
LockSessions();
LockThread();
//
// search for session
session = NULL;
@ -245,36 +239,30 @@ int Network::ClientLoop(UNIX *client) {
break;
}
}
UnLockSessions();
UnLockThread();
}
if (session) {
JSONElement je;
int retval;
LockThread();
retval = session->ProcessData(&json, &jsonout);
UnLockThread();
len = BUFFERSIZE;
if (retval) {
je.Clear();
je.Set("success", 1);
jsonout.AddObject(je);
je.Clear();
je.Set("serverstatus", server->GetStatus());
jsonout.AddObject(je);
}
else {
je.Clear();
je.Set("success", 0);
jsonout.AddObject(je);
je.Clear();
je.Set("serverstatus", "ERROR");
jsonout.AddObject(je);
}
s = jsonout.ToString();
// printf ("***************************** %s:%d ---> send:\n\n\n%s\n\n\n", __FILE__, __LINE__, s.c_str());
l = client->Write((char*)s.c_str(), strlen(s.c_str()));
// printf ("\n\n Network::ClientLoop %s:%d strlen:%ld result:%ld \n\n\n", __FILE__, __LINE__, strlen(s.c_str()), l);
client->Write((char*)s.c_str(), strlen(s.c_str()));
result = 1;
}
else {

@ -11,7 +11,6 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
@ -29,7 +28,7 @@ using namespace std;
#include "modelbahn.h"
#include "json.h"
#include "debug.h"
extern int next_sessionID;
@ -39,12 +38,6 @@ private:
int sessionID;
int randomID;
list<string> changes;
pthread_mutex_t mtxchanges;
// void LockChanges() { debug (0," ****** %s ", __FUNCTION__); pthread_mutex_lock(&mtxchanges); };
// void UnLockChanges() { pthread_mutex_unlock(&mtxchanges); debug (0," ****** %s ", __FUNCTION__); };
void LockChanges() { pthread_mutex_lock(&mtxchanges); };
void UnLockChanges() { pthread_mutex_unlock(&mtxchanges); };
void AddJSONRailway(JSONParse *jp);
void DelJSONRailway(JSONParse *jp);
@ -55,7 +48,6 @@ private:
void AddJSONSensor(JSONParse *jp);
void DelJSONSensor(JSONParse *jp);
void SetJSONSensorActive(JSONParse *jp);
void AddJSONInterface(JSONParse *jp);
void DelJSONInterface(JSONParse *jp);
@ -63,20 +55,6 @@ private:
void AddJSONLocomotive(JSONParse *jp);
void DelJSONLocomotive(JSONParse *jp);
void SetJSONLocomotive(JSONParse *jp);
void SetJSONLocoDest(JSONParse *jp);
void SetJSONLocoAssign(JSONParse *jp);
void SetJSONLocoReset(JSONParse *jp);
void SetJSONLocoMan(JSONParse *jp);
void SetJSONLocoAutoMan(JSONParse *jp);
void SetJSONLocoAuto(JSONParse *jp);
void SetJSONLocoAutoRand(JSONParse *jp);
void SetJSONLocoAutoShed(JSONParse *jp);
void BlockJSONOff(JSONParse *jp);
void BlockJSONClear(JSONParse *jp);
void AddJSONBlock(JSONParse *jp);
void DelJSONBlock(JSONParse *jp);
public:
Session(int rid);
@ -100,8 +78,6 @@ class Network {
private:
void ThreadProcess();
pthread_mutex_t mtx;
pthread_mutex_t mtxsessions;
pthread_t thread;
int thread_running;
@ -113,15 +89,14 @@ private:
int ClientLoop(UNIX *u);
UNIX sockserver;
void _ChangeListPushToAll (string changes); // not thread save
friend class Session;
public:
Network();
~Network();
void Lock() { pthread_mutex_lock(&mtx); };
void UnLock() { pthread_mutex_unlock(&mtx); };
void LockSessions() { pthread_mutex_lock(&mtxsessions); };
void UnLockSessions() { pthread_mutex_unlock(&mtxsessions); };
int LockThread();
int UnLockThread();
int Start();
void Stop();

File diff suppressed because it is too large Load Diff

@ -25,7 +25,6 @@ enum {
#define RAILWAYS_MAX_WIDTH 500
#define RAILWAYS_MAX_HEIGHT 500
#define RAILWAYS_LOCKF_KEEPSTART 0x0001 // keep start
// direktion
//
@ -41,20 +40,7 @@ enum {
// | | | /| |\ | | |
// +---+ +---+ +---+ +---+
//
// Enter from
// 0
// +---+
// | |
// 3| |1
// | |
// +---+
// 2
enum {
EF_NORTH = 0,
EF_EAST,
EF_SOUTH,
EF_WEST
};
struct s_Railway {
int type;
@ -65,24 +51,8 @@ struct s_Railway {
int maxspeed;
int flags; // not defined yet
char name[REFERENCENAME_LEN]; // reference name
char lockedby[REFERENCENAME_LEN]; // element locked by locreference (only set by server, not by JSON/Webinterface)
} typedef Railway;
struct s_findway_data {
int x;
int y;
int enterfrom; // enter field from clock view (0 = North, 3 = East... 6 ... 9)
int oldx;
int oldy;
int oldenterfrom;
int dist;
string way;
};
struct s_findway_map {
int e; // save entryfrom as (1 << entryfrom)
int score;
};
class Railways {
private:
@ -93,17 +63,11 @@ class Railways {
int changed;
pthread_mutex_t mtx;
int Lock();
int UnLock();
int GetRIdx(int x, int y);
JSONParse _GetJSONRailway(int x, int y);
void _New (int w, int h);
void DebugPrintFindWay(struct s_findway_map *fw);
int _FindReference(int *x, int *y, string name, int cnt);
int _SplitBlockIsFreeAndAllowed(string loconame, int locoflags, string block);
int _NextPosIsValid(string loconame, int locoflags, struct s_findway_data *fwd);
string GetDestBlock(int locoflags, string blockend);
public:
Railways();
@ -121,22 +85,11 @@ class Railways {
void ClearChanged() { changed = 0; };
int Change(Railway *rw);
void ClearLockedby(string name);
Railway RailwayGet(int x, int y) {return railways[GetRIdx(x, y)];}; // no lock
Railway RailwayGet(int x, int y) {return railways[GetRIdx(x, y)];};
JSONParse GetJSONRailway(int x, int y);
JSONParse GetJSONTrack();
void GetJSONAll(JSONParse *json);
Railway GetRailwayFromJSON(JSONParse *j);
int FindReference(int *x, int *y, string name, int cnt);
int FindWay(string blockstart, string blockend, string lockedfor, string *next);
int FindWayCheckIfNoDoubleTurnouts (string *next);
int FindRandomWay(string blockstart, string lockedfor, string *next);
int LockWay (string way, string lockedby, int lockonoff, int flags);
int SetLockedby (int x, int y, string name, int locked);
struct s_findway_data NextPos(struct s_findway_data pos, int dirtype);
};
#endif

@ -7,12 +7,9 @@
Sensors::Sensors () {
changed = 0;
sensors = (Sensor*) malloc(sizeof(Sensor)*SENSORS_MAX);
memset (sensors, 0x0, sizeof(Sensor)*SENSORS_MAX);
max = SENSORS_MAX;
pthread_mutex_init(&mtx, NULL);
};
Sensors::~Sensors() {
free (sensors);
sensors = NULL;
@ -20,46 +17,7 @@ Sensors::~Sensors() {
};
int Sensors::GetActive(string name) {
int i;
int res = 0;
Lock();
for (i = 0; i < max; i++) if (sensors[i].name[0] != 0) {
if (name.compare(sensors[i].name) == 0) {
if (sensors[i].flags & SENSOR_F_ACTIVE) res = 1;
break;
}
}
UnLock();
return res;
};
int Sensors::SetActive(string name, int value) {
int i;
JSONParse jp;
Lock();
for (i = 0; i < max; i++) if (sensors[i].name[0] != 0) {
if (name.compare(sensors[i].name) == 0) {
if (value) sensors[i].flags |= SENSOR_F_ACTIVE;
else sensors[i].flags &= ~SENSOR_F_ACTIVE;
jp.Clear();
jp.AddObject("sensor", _GetJSON(i));
if(network) network->ChangeListPushToAll(jp.ToString());
break;
}
}
UnLock();
return 1;
};
int Sensors::Lock() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
@ -151,42 +109,6 @@ Sensor Sensors::GetSensorFromJSON(JSONParse *j) {
};
int Sensors::Get(string name, Sensor *dest) {
int i;
if (dest == NULL) return 0;
Lock();
for (i = 0; i < max; i++) if (sensors[i].name[0] != 0)
if (name.compare(sensors[i].name) == 0) {
(*dest) = sensors[i];
UnLock();
return 1;
}
UnLock();
return 0;
};
int Sensors::Get(int idx, Sensor *dest) {
int i;
if (dest == NULL) return 0;
Lock();
for (i = 0; i < max; i++) if (sensors[i].name[0] != 0)
if (idx == i) {
(*dest) = sensors[i];
UnLock();
return 1;
}
UnLock();
return 0;
};
int Sensors::Change(Sensor *se) {
int i;
int ifree = -1;
@ -211,7 +133,6 @@ int Sensors::Change(Sensor *se) {
}
changed = 1;
UnLock();
return 1;
@ -244,8 +165,7 @@ int Sensors::Delete(string name) {
void Sensors::SetFromBus(string name, int addr, int active) {
int i;
JSONParse jp;
debug (0, "* Sensor Interface:%s Addr:%d changed:%d", name.c_str(), addr, active);
for (i = 0; i < max; i++) if (sensors[i].name[0] != 0) {
if (strncmp (sensors[i].ifname, name.c_str(), REFERENCENAME_LEN) == 0 && sensors[i].addr == addr) {
debug (0, "* Sensor %s changed:%d", sensors[i].name, active);

@ -35,10 +35,6 @@ class Sensors {
void ClearChanged() { changed = 0; };
int Change(Sensor *se);
int Get(int idx, Sensor *dest);
int GetActive(string name);
int SetActive(string name, int value);
int Get(string name, Sensor *dest);
int Delete(string name);
JSONParse GetJSON(string name);

@ -73,7 +73,7 @@ int Server::Load(string fn) {
close (fd);
// everything read?
if (len < (size_t) sbuf.st_size) {
if (len < sbuf.st_size) {
free (buf);
debug (DEBUG_ERROR, "* Reading Track File Failed. (len < filesize)");
return 0;
@ -137,14 +137,6 @@ int Server::Load(string fn) {
turnouts.Change(&to);
}
//
// read blocks
Block bl;
for (i = 0; json.GetObjectIdx("blocks", i, &jtmp); i++) {
bl = blocks.GetBlockFromJSON(&jtmp);
blocks.Change(&bl);
}
railways.ClearChanged();
return 1;
@ -190,10 +182,6 @@ int Server::Save(string fn) {
// write all turnouts
turnouts.GetJSONAll(&json);
//
// write all turnouts
blocks.GetJSONAll(&json);
f = fopen (fn.c_str(), "w");
fprintf (f, "%s", json.ToString().c_str());

@ -22,11 +22,13 @@
#include "modelbahn.h"
#include "server.h"
int Server::Start() {
int err;
thread_running = 1;
pthread_attr_t attr;
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
thread_running = 1;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
err = pthread_create (&thread, &attr, ThreadEntry, this);
@ -40,18 +42,9 @@ int Server::Start() {
Server::Server() {
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
thread = 0;
thread_running = 0;
railways.SetSize(64, 32);
status_text = "init server";
mode = SMODE_STARTUP;
data_reset.mr_idx = -1;
data_reset.mr_step = SMRESET_STEP_INIT;
gettimeofday(&data_reset.mr_timestamp, NULL);
railways.SetSize(200, 200);
Load ();
};
@ -61,99 +54,12 @@ Server::~Server() {
};
int Server::TurnoutSet(string name, int active) {
int x, y, locked = 0;
string lockedby;
int cnt = 0;
Railway r;
//
// check if locked
while (server->railways.FindReference(&x, &y, name, (cnt++))) {
r = server->railways.Get(x, y);
debug (0, "%s:%d Reference %d,%d Name:%s Lockedby:%s", __FILE__, __LINE__, x, y, r.name, r.lockedby);
if (r.lockedby[0] != 0) {
locked = 1;
lockedby = r.lockedby;
}
}
if (simulation) {
int flags;
debug (0, "%s:%d WARNING SIMULATION MODE", __FILE__, __LINE__);
flags = turnouts.GetFlags(turnouts.GetIdx(name));
if (flags & TURNOUT_F_TURNOUT) flags &= ~TURNOUT_F_TURNOUT;
else flags |= TURNOUT_F_TURNOUT;
turnouts.SetFlags(turnouts.GetIdx(name), flags);
turnouts.Set(name, active);
}
if (locked == 0) return turnouts.Set(name, active);
else {
debug (0, "%s:%d SetJSONTurnout Element %s is locked by %s", __FILE__, __LINE__, name.c_str(), lockedby.c_str());
}
return 0;
}
//
// server thread will cycle as long as running is set to true
// most important in each cycle there will be
void Server::ThreadProcess() {
int i = 0;
int timeout10s;
int cyclelooptime_max = 0;
int cycletime_max = 0;
struct timeval tv_loop, tv;
gettimeofday (&tv, NULL);
gettimeofday (&tv_loop, NULL);
timeout10s = tv.tv_sec + 10;
while (running) {
interfaces.Loop();
turnouts.Loop();
//
// startup process
if (mode == SMODE_STARTUP) {
mode = SMODE_MANUAL;
printf ("%s:%d ************************************************************ fix me\n", __FILE__, __LINE__);
SetModeReset(); // currently there is not much to do.
}
//
// reset all internal data
else if (mode == SMODE_RESET)
CycleModeReset();
//
// mode manual
else if (mode == SMODE_MANUAL) {
}
//
// mode auto
else if (mode == SMODE_AUTO) {
server->locomotives.Loop();
}
gettimeofday (&tv, NULL);
i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000;
if (i > cycletime_max) cycletime_max = i;
if (i < 25 && i >= 0) usleep (25000 - i*1000);
gettimeofday (&tv, NULL);
i = (tv.tv_sec-tv_loop.tv_sec) * 1000 + (tv.tv_usec - tv_loop.tv_usec) / 1000;
if (i > cyclelooptime_max) cyclelooptime_max = i;
if (tv_loop.tv_sec > timeout10s) {
timeout10s = tv.tv_sec + 10;
debug (DEBUG_INFO, "Server::ThreadProcess max Cycletime: %dms Cyclelooptime:%dms", cycletime_max, cyclelooptime_max);
cycletime_max = 0;
cyclelooptime_max = 0;
}
tv_loop = tv;
usleep (25000);
}
debug (0, "Server::ThreadProcess Finished");
thread_running = 0;
@ -161,11 +67,13 @@ void Server::ThreadProcess() {
void Server::LockThread() {
debug(DEBUG_INFO, "%s:%d Server::LockThread", __FILE__, __LINE__);
pthread_mutex_lock (&mtx);
};
void Server::UnLockThread() {
debug (DEBUG_INFO, "%s:%d Server::UnLockThreads", __FILE__, __LINE__);
pthread_mutex_unlock (&mtx);
};
@ -181,7 +89,6 @@ void Server::GetJSONAll(JSONParse *json) {
sensors.GetJSONAll(json);
locomotives.GetJSONAll(json);
turnouts.GetJSONAll(json);
blocks.GetJSONAll(json);
}
@ -195,170 +102,4 @@ bool Server::IsChanged() {
}
//
// Set Mode Auto
void Server::SetModeAuto() {
debug (0, "%s:%d * Set Mode Auto", __FILE__, __LINE__);
if (mode == SMODE_MANUAL) {
mode = SMODE_AUTO;
status_text = "Mode Auto";
}
}
//
// Set Mode Manual
void Server::SetModeManual() {
debug (0, "%s:%d * Set Mode Manual", __FILE__, __LINE__);
mode = SMODE_MANUAL;
status_text = "Mode Manual";
}
//
// run a single cycle in reset mode
// each step will only reset one single step.
#define INTERFACE_LOCO_TIME 250
#define INTERFACE_TURN_TIME 750
void Server::CycleModeReset() {
JSONParse json;
list<JSONElement> elements;
list<JSONElement>::iterator iter;
json.Clear();
// debug (0, "* CycleModeReset Step:%d", data_reset.mr_step);
if (data_reset.mr_step == SMRESET_STEP_INIT) {
//
// init reset
data_reset.mr_idx = -1;
data_reset.mr_step++;
}
else if (data_reset.mr_step == SMRESET_STEP_LOCKS) {
//
// clear all locks
debug (0, "* Clear all Locks", data_reset.mr_lastelm.c_str());
data_reset.mr_idx = -1;
data_reset.mr_step++;
}
else if (data_reset.mr_step == SMRESET_STEP_INTERFACES) {
//
// clear locks
data_reset.mr_idx = -1;
data_reset.mr_step++;
}
else if (data_reset.mr_step == SMRESET_STEP_LOCOMOTIVES) {
//
// reset locomotives, cycle 30ms per locomotive
if (data_reset.mr_idx < 0 || timer_get(&data_reset.mr_timestamp) > INTERFACE_LOCO_TIME) {
if (data_reset.mr_idx < -1) data_reset.mr_idx = -1;
data_reset.mr_idx++;
data_reset.mr_lastelm = locomotives.GetName(data_reset.mr_idx);
timer_start (&data_reset.mr_timestamp);
if (data_reset.mr_lastelm.length() > 0) {
debug (0, "* Reset Locomotive %s", data_reset.mr_lastelm.c_str());
LocomotiveSetReverse(data_reset.mr_lastelm, 0);
LocomotiveSetSpeed(data_reset.mr_lastelm, 0);
}
else {
data_reset.mr_idx = -1;
data_reset.mr_step++;
data_reset.mr_lastelm = "";
}
}
}
else if (data_reset.mr_step == SMRESET_STEP_TURNOUTS) {
//
// reset turnouts
if (data_reset.mr_idx < 0 || timer_get(&data_reset.mr_timestamp) > INTERFACE_TURN_TIME) {
int flags, active;
if (data_reset.mr_idx < -1) data_reset.mr_idx = -1;
data_reset.mr_idx++;
data_reset.mr_lastelm = turnouts.GetName(data_reset.mr_idx);
if (data_reset.mr_lastelm.length() > 0) {
//
// reset output/turnout only if not a relais
flags = turnouts.GetFlags(data_reset.mr_idx);
if ((flags & TURNOUT_F_ISRELAIS) == 0) {
if (flags & TURNOUT_F_TURNOUT) active = 1;
else active = 0;
timer_start (&data_reset.mr_timestamp);
debug (0, "* Reset Turnout %s", data_reset.mr_lastelm.c_str());
TurnoutSet(data_reset.mr_lastelm, active);
}
}
else {
data_reset.mr_idx = -1;
data_reset.mr_step++;
data_reset.mr_lastelm = "";
}
}
}
else if (data_reset.mr_step == SMRESET_STEP_SENSORS) {
//
// reset sensors
// all can be done in one single cycle.
//
int i; // index of sensor
int oldflags; // old flags
Sensor sensor; // sensor data
for (i = 0; sensors.Get(i, &sensor) == 1; i++) {
oldflags = sensor.flags;
sensor.flags &= ~(SENSOR_F_ACTIVE);
debug (0, "* Reset Sensor: '%s' (%d -> %d)", sensor.name, oldflags, sensor.flags);
if (oldflags != sensor.flags) // only update if needed
sensors.Change(&sensor);
}
sensors.GetJSONAll(&json);
data_reset.mr_idx = -1;
data_reset.mr_step++;
}
else {
SetModeManual();
}
//
// adding update data
elements = json.GetElements();
for (iter = elements.begin(); iter != elements.end(); iter++) {
if (network) network->ChangeListPushToAll("{"+(*iter).GetString()+"}");
}
}
//
// Set Mode Error
void Server::SetModeError(string text) {
debug (0, "%s:%d * Set Mode Error :'%s'", __FILE__, __LINE__, text.c_str());
status_text = "Error:'" + text + "'";
}
//
// Set Mode Reset
void Server::SetModeReset() {
debug (0, "%s:%d * Set Reset Data", __FILE__, __LINE__);
status_text = "Mode Reset";
mode = SMODE_RESET;
data_reset.mr_step = SMRESET_STEP_INIT;
data_reset.mr_idx = -1;
data_reset.mr_lastelm = "";
gettimeofday(&data_reset.mr_timestamp, NULL);
};
string Server::GetStatus(void) {
string retval;
LockThread();
retval = status_text;
UnLockThread();
return retval;
};

@ -27,46 +27,10 @@
#include "railway.h"
#include "locomotive.h"
#include "sensor.h"
#include "interfaces.h"
#include "block.h"
enum SMODE {
SMODE_STARTUP,
SMODE_RESET,
SMODE_MANUAL,
SMODE_AUTO,
SMODE_MAX
};
enum SMRESET {
SMRESET_STEP_INIT = 0,
SMRESET_STEP_LOCKS,
SMRESET_STEP_LOCOMOTIVES,
SMRESET_STEP_TURNOUTS,
SMRESET_STEP_SENSORS,
SMRESET_STEP_INTERFACES,
SMRESET_STEP_MAX
};
struct s_ModeResetData{
int mr_step; // current step
struct timeval mr_timestamp; // timestamp ( needed for times )
int mr_idx; // mode index
string mr_lastelm; // last element
} typedef ModeResetData;
#include "interface.h"
class Server {
private:
int mode; // holds the current mode
int mode_progress; // to return a value from 0-100
string status_text; // some text
ModeResetData data_reset;
pthread_mutex_t mtx;
pthread_t thread;
int thread_running;
@ -75,7 +39,6 @@ private:
Railways railways;
Locomotives locomotives;
Interfaces interfaces;
Blocks blocks;
void ThreadProcess();
void LoopCheckChanges();
@ -89,8 +52,6 @@ private:
friend class Locomotives;
friend class Sensors;
friend class Turnouts;
friend class Blocks;
friend class Railways;
public:
/////////////////////////////////////////
// functions here are required to be thread save
@ -113,23 +74,6 @@ public:
int GetHeight() { return railways.GetHeight(); };
int GetWidth() { return railways.GetWidth(); };
//
// Load Save Part
int Load();
int Save();
//
// Reset dynamic data
JSONParse GetJSONServerStatus();
void SetModeReset(); // mode Reset if finished will go to Manual
void SetModeManual(); // Manual Mode
void SetModeAuto(); // only allowed if Manual was set
void SetModeError(string text); // will cut power and keep this mode, until reset or Mode Manual
void CycleModeReset(); // one Cycle in mode reset
string GetStatus(); // return status
/////////////////////////////////////////
// Railway
int RailwayChange(Railway *rw) { return railways.Change(rw);};
@ -143,7 +87,8 @@ public:
Turnout TurnoutFromJSON(JSONParse *j) { return turnouts.GetTurnoutFromJSON(j); };
JSONParse TurnoutGetJSON(string name) { return turnouts.GetJSON(name); };
int TurnoutDelete(string name) { return turnouts.Delete(name); };
int TurnoutSet(string name, int active);
int TurnoutSet(string name, int active) { return turnouts.Set(name, active); };
/////////////////////////////////////////
// Interface
@ -159,16 +104,7 @@ public:
JSONParse LocomotiveGetJSON(string name) { return locomotives.GetJSON(name); };
int LocomotiveDelete(string name) { return locomotives.Delete(name); };
int LocomotiveSetSpeed(string name, int speed) { return locomotives.SetSpeed(name, speed); };
int LocomotiveSetReverse(string name, int reverse) { return locomotives.SetReverse(name, reverse); };
int LocomotiveSetFunction(string name, int func, int value) { return locomotives.SetFunction(name, func, value); };
int LocomotiveSetDest(string name, string block, int direction) { return locomotives.SetDestination(name, block, direction); };
int LocomotiveSetAssign(string name, string block, int direction) { return locomotives.SetAssign(name, block, direction); };
int LocomotiveReset(string name) { return locomotives.Reset(name); };
int LocomotiveSetMan(string name) { return locomotives.SetModeMan(name); };
int LocomotiveSetAuto(string name) { return locomotives.SetModeAuto(name); };
int LocomotiveSetAutoMan(string name) { return locomotives.SetModeAutoMan(name); };
int LocomotiveSetAutoRand(string name) { return locomotives.SetModeAutoRand(name); };
int LocomotiveSetAutoShed(string name) { return locomotives.SetModeAutoShed(name); };
/////////////////////////////////////////
// Sensor
@ -176,26 +112,22 @@ public:
Sensor SensorFromJSON(JSONParse *j) { return sensors.GetSensorFromJSON(j); };
JSONParse SensorGetJSON(string name) { return sensors.GetJSON(name); };
int SensorDelete(string name) { return sensors.Delete(name); };
int SensorSetActive(string name, int value) { return sensors.SetActive(name, value); };
/////////////////////////////////////////
// Blocks
int BlockChange(Block *s) { return blocks.Change(s); };
Block BlockFromJSON(JSONParse *j) { return blocks.GetBlockFromJSON(j); };
JSONParse BlockGetJSON(string name) { return blocks.GetJSON(name); };
int BlockDelete(string name) { return blocks.Delete(name); };
int BlockSetOff(string name) { return blocks.SetOff(name); };
int BlockClear(string name) { return blocks.Clear(name); };
void GetJSONAll(JSONParse *json);
/////////////////////////////////////////
// reports from interfaces
int LocomotiveAddrSpeed(string name, int addr, int speed) { return locomotives.SetSpeedFromBus(name, addr, speed); };
int LocomotiveAddrFunction(string name, int addr, int func) { return locomotives.SetFunctionFromBus(name, addr, func); };
int LocomotiveAddrDirection(string name, int addr, int reverse) { return locomotives.SetDirectionFromBus(name, addr, reverse); };
int TurnoutAddrMode(string name, int addr, int active) { turnouts.SetFromBus(name, addr, active); return 1; };
int SensorAddrChange(string name, int addr, int active) { sensors.SetFromBus(name, addr, active); return 1; };
//
// Load Save Part
int Load();
int Save();
protected:
static void *ThreadEntry (void *This) { ((Server*)This)->ThreadProcess(); return NULL;};
};

@ -9,11 +9,7 @@ int Session::SendData(UNIX *u, string data) {
return 0;
};
Session::Session(int rid) {
mtxchanges = { 0 };
mtxchanges = PTHREAD_MUTEX_INITIALIZER;
sessionID = random();
randomID = rid;
changes.clear();
@ -47,7 +43,6 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
// editing elements
//
debug (0, "%s:%d JIN:%s", __FILE__, __LINE__, jin->ToString().c_str());
if (command.compare("addrailway") == 0) {
debug (0, "* Session Add Railways");
AddJSONRailway(jin);
@ -64,10 +59,6 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
debug (0, "* Session Del Interface");
DelJSONInterface(jin);
}
//
// turnouts
//
else if (command.compare("addsensor") == 0) {
debug (0, "* Session Add Sensor");
AddJSONSensor(jin);
@ -76,49 +67,14 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
debug (0, "* Session del Sensor");
DelJSONSensor(jin);
}
else if (command.compare("sensorSetActive") == 0) {
debug (0, "* Session Sensor Set Active");
printf ("%s:%d jin:%s", __FILE__, __LINE__, jin->ToString().c_str());
SetJSONSensorActive(jin);
}
//
// turnouts
//
else if (command.compare("addturnout") == 0) {
debug (0, "* Session Add Turnout");
AddJSONTurnout(jin);
}
else if (command.compare("delturnout") == 0) {
debug (0, "* Session Del Turnout");
debug (0, "* Session del Turnout");
DelJSONTurnout(jin);
}
else if (command.compare("setturnout") == 0) {
SetJSONTurnout(jin);
}
//
// Blocks
//
else if (command.compare("addblock") == 0) {
debug (0, "* Session Add Block");
AddJSONBlock(jin);
}
else if (command.compare("delblock") == 0) {
debug (0, "* Session Del Block");
DelJSONBlock(jin);
}
else if (command.compare("blockoff") == 0) {
BlockJSONOff(jin);
}
else if (command.compare("blockclear") == 0) {
BlockJSONClear(jin);
}
//
// Locomotive
//
else if (command.compare("addlocomotive") == 0) {
debug (0, "* Session Add Locomotive");
AddJSONLocomotive(jin);
@ -127,35 +83,21 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
debug (0, "* Session Del Locomotive");
DelJSONLocomotive(jin);
}
//
// locomotives
//
else if (command.compare("setlocomotive") == 0) {
SetJSONLocomotive(jin);
}
else if (command.compare("locomotivedestination") == 0) {
SetJSONLocoDest(jin);
}
else if (command.compare("locomotiveassign") == 0) {
SetJSONLocoAssign(jin);
}
else if (command.compare("locomotivesetman") == 0) {
SetJSONLocoMan(jin);
}
else if (command.compare("locomotivesetauto") == 0) {
SetJSONLocoAuto(jin);
}
else if (command.compare("locomotivesetautoman") == 0) {
SetJSONLocoAutoMan(jin);
}
else if (command.compare("locomotivesetautorand") == 0) {
SetJSONLocoAutoRand(jin);
}
else if (command.compare("locomotivesetautoshed") == 0) {
SetJSONLocoAutoShed(jin);
}
else if (command.compare("locomotivereset") == 0) {
SetJSONLocoReset(jin);
//
// locomotives
//
else if (command.compare("setturnout") == 0) {
SetJSONTurnout(jin);
}
//
// poweron / poweroff / save and resetdata
// poweron / poweroff
//
else if (command.compare("poweron") == 0) {
debug (0, "* Session Poweron");
@ -165,32 +107,19 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
debug (0, "* Session Poweroff");
server->PowerOnOff(0);
}
else if (command.compare("save") == 0) {
debug (0, "* Save All");
server->Save();
}
else if (command.compare("serverreset") == 0) {
debug (0, "* Server Set to Reset");
server->SetModeReset();
}
else if (command.compare("servermanual") == 0) {
debug (0, "* Server Set to Manual");
server->SetModeManual();
}
else if (command.compare("serverauto") == 0) {
debug (0, "* Server Set to Auto");
server->SetModeAuto();
}
else if (command.compare("getall") == 0) {
json.Clear();
server->GetJSONAll(&json);
// debuggin maybe we need to fix this somehow
elements = json.GetElements();
for (iter = elements.begin(); iter != elements.end(); iter++) {
// printf ("*********************** Session::ProcessData %s:%d\n\n***\n%s\n***\n", __FILE__, __LINE__, (*iter).GetString().c_str());
for (iter = elements.begin(); iter != elements.end(); iter++)
ChangeListPush("{"+(*iter).GetString()+"}");
}
}
else {
debug (DEBUG_ERROR | DEBUG_SESSION, "%s:%d Unknown command: '%s' JSON:%s",
@ -212,9 +141,7 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
// add chenges which need to be send to the clients
//
void Session::ChangeListPush(string chng) {
LockChanges();
changes.push_back(chng);
UnLockChanges();
};
@ -231,17 +158,18 @@ JSONElement Session::ChangeListGet() {
je.name = "changes";
je.value = "[";
LockChanges();
for (iter = changes.begin(); iter != changes.end(); iter++) {
if (iter != changes.begin()) je.value += ",\n ";
else je.value += "\n ";
je.value += (*iter);
}
changes.clear();
UnLockChanges();
je.value += "]";
// debug (0, "* Session::ChangeListGet string:'%s'", je.GetString().c_str());
return je;
}
@ -270,7 +198,7 @@ void Session::AddJSONRailway(JSONParse *jp) {
server->RailwayChange(&r);
jout.Clear();
jout.AddObject("railway", server->RailwayGetJSONRailway(r.x, r.y));
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
}
@ -297,7 +225,7 @@ void Session::DelJSONRailway(JSONParse *jp) {
server->RailwayChange(&r);
jout.Clear();
jout.AddObject("railway", server->RailwayGetJSONRailway(r.x, r.y));
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
}
@ -321,7 +249,7 @@ void Session::AddJSONInterface(JSONParse *jp) {
server->InterfaceChange(&iface);
jout.Clear();
jout.AddObject("interface", server->InterfaceGetJSON(iface.name));
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -347,7 +275,7 @@ void Session::DelJSONInterface(JSONParse *jp) {
jout.Clear();
s = iface.name;
jout.AddObject("interfacedelete", s);
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -371,7 +299,7 @@ void Session::AddJSONSensor(JSONParse *jp) {
server->SensorChange(&se);
jout.Clear();
jout.AddObject("sensor", server->SensorGetJSON(se.name));
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -391,13 +319,13 @@ void Session::DelJSONSensor(JSONParse *jp) {
jp->GetObject("sensor", &jtmp);
se = server->SensorFromJSON(&jtmp);
if (se.name[0] != 0) {
debug (0, "%s:%d DelJSONSensor Element %s", __FILE__, __LINE__, se.name);
debug (0, "%s:%d DelJSONTurnout Element %s", __FILE__, __LINE__, se.name);
// add element
server->SensorDelete(se.name);
jout.Clear();
s = se.name;
jout.AddObject("sensordelete", s);
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -421,7 +349,7 @@ void Session::AddJSONLocomotive(JSONParse *jp) {
server->LocomotiveChange(&loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco.name));
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -449,12 +377,6 @@ void Session::SetJSONLocomotive(JSONParse *jp) {
debug (0, "%s:%d SetJSONLocomotive Element %s Speed:%d", __FILE__, __LINE__, loconame.c_str(), speed);
server->LocomotiveSetSpeed(loconame, speed);
}
if (jloco.GetValueInt("reverse", &value) == 1) {
//
// reverse
debug (0, "%s:%d SetJSONLocomotive Element %s Reverse:%d", __FILE__, __LINE__, loconame.c_str(), value);
server->LocomotiveSetReverse(loconame, value);
}
if (jloco.GetValueInt("function", &func) == 1 && jloco.GetValueInt("value", &value) == 1) {
//
// set function
@ -463,7 +385,7 @@ void Session::SetJSONLocomotive(JSONParse *jp) {
}
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loconame));
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -478,9 +400,10 @@ void Session::DelJSONLocomotive(JSONParse *jp) {
JSONParse jout;
string s;
server->LockThread();
jp->GetObject("locomotive", &jloco);
loco = server->LocomotiveFromJSON(&jloco);
server->LockThread();
if (loco.name[0] != 0) {
debug (0, "%s:%d DelJSONLocomotive Element %s", __FILE__, __LINE__, loco.name);
// add element
@ -488,137 +411,12 @@ void Session::DelJSONLocomotive(JSONParse *jp) {
jout.Clear();
s = loco.name;
jout.AddObject("locomotivedelete", s);
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
void Session::SetJSONLocoDest(JSONParse *jp) {
string loco;
string block;
int reverse;
JSONParse jout;
jp->GetValue("locomotive", &loco);
jp->GetValue("block", &block);
jp->GetValueInt("reverse", &reverse);
server->LockThread();
server->LocomotiveSetDest(loco, block, reverse);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAssign(JSONParse *jp) {
string loco;
string block;
int reverse;
JSONParse jout;
jp->GetValue("locomotive", &loco);
jp->GetValue("block", &block);
jp->GetValueInt("reverse", &reverse);
server->LockThread();
server->LocomotiveSetAssign(loco, block, reverse);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoReset(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveReset(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoMan(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetMan(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAutoMan(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetAutoMan(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAuto(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetAuto(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAutoRand(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetAutoRand(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAutoShed(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetAutoShed(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
//
// add new Turnout
//
@ -637,7 +435,7 @@ void Session::AddJSONTurnout(JSONParse *jp) {
server->TurnoutChange(&to);
jout.Clear();
jout.AddObject("turnout", server->TurnoutGetJSON(to.name));
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -663,7 +461,7 @@ void Session::DelJSONTurnout(JSONParse *jp) {
jout.Clear();
s = to.name;
jout.AddObject("turnoutdelete", s);
if (network) network->ChangeListPushToAll(jout.ToString());
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
@ -675,7 +473,6 @@ void Session::DelJSONTurnout(JSONParse *jp) {
void Session::SetJSONTurnout(JSONParse *jp) {
JSONParse jout;
string name;
string lockedby;
int active;
server->LockThread();
@ -688,113 +485,14 @@ void Session::SetJSONTurnout(JSONParse *jp) {
// activate
debug (0, "%s:%d SetJSONTurnout Element %s active:%d", __FILE__, __LINE__, name.c_str(), active);
server->TurnoutSet(name, active);
}
server->UnLockThread();
};
//
// add new block
//
void Session::AddJSONBlock(JSONParse *jp) {
Block bl;
JSONParse jtmp;
JSONParse jout;
server->LockThread();
jp->GetObject("block", &jtmp);
bl = server->BlockFromJSON(&jtmp);
if (bl.name[0] != 0) {
debug (0, "%s:%d AddJSONBlock Element %s", __FILE__, __LINE__, bl.name);
// add element
server->BlockChange(&bl);
jout.Clear();
jout.AddObject("block", server->BlockGetJSON(bl.name));
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
//
// delete block
//
void Session::DelJSONBlock(JSONParse *jp) {
Block bl;
JSONParse jtmp;
JSONParse jout;
string s;
server->LockThread();
jp->GetObject("block", &jtmp);
bl = server->BlockFromJSON(&jtmp);
if (bl.name[0] != 0) {
debug (0, "%s:%d DelJSONBlock Element %s", __FILE__, __LINE__, bl.name);
// add element
server->BlockDelete(bl.name);
jout.Clear();
s = bl.name;
jout.AddObject("blockdelete", s);
if (network) network->ChangeListPushToAll(jout.ToString());
jout.AddObject("turnout", server->TurnoutGetJSON(name));
if (network) network->_ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
void Session::BlockJSONOff(JSONParse *jp) {
string name;
JSONParse jout;
jp->GetValue("block", &name);
server->LockThread();
server->BlockSetOff(name);
jout.Clear();
jout.AddObject("block", server->BlockGetJSON(name));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::BlockJSONClear(JSONParse *jp) {
string name;
JSONParse jout;
jp->GetValue("block", &name);
server->LockThread();
server->BlockClear(name);
jout.Clear();
jout.AddObject("block", server->BlockGetJSON(name));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
//
// add new block
//
void Session::SetJSONSensorActive(JSONParse *jp) {
string name;
int enabled;
JSONParse jtmp;
JSONParse jout;
server->LockThread();
jp->GetValue("sensor", &name);
jp->GetValueInt("enabled", &enabled);
server->SensorSetActive(name, enabled);
// jout.Clear();
// jout.AddObject("block", server->BlockGetJSON(bl.name));
// if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
/*
res = json.GetValue("command", &value);
if (res && value.compare("addelemens") == 0) {

@ -5,9 +5,7 @@
Turnouts::Turnouts() {
changed = 0;
turnouts = (Turnout*) malloc(sizeof(Turnout)*TURNOUTS_MAX);
memset (turnouts, 0x0, sizeof(Turnout)*TURNOUTS_MAX);
max = TURNOUTS_MAX;
pthread_mutex_init(&mtx, NULL);
};
Turnouts::~Turnouts() {
@ -41,7 +39,6 @@ JSONParse Turnouts::_GetJSON(int idx) {
json.AddObject("addr", turnouts[idx].addr);
json.AddObject("activetimeout", turnouts[idx].activetimeout);
json.AddObject("flags", turnouts[idx].flags);
json.AddObject("lockedby", turnouts[idx].lockedby);
return json;
};
@ -166,33 +163,20 @@ int Turnouts::Delete(string name) {
int Turnouts::Set(string name, int value) {
int i;
JSONParse jp;
//
Lock();
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
if (name.compare(turnouts[i].name) == 0) {
debug (0, "%s:%d Turnout::Set: Name:%s Flags:%d[%c%c%c%c] Value:%d", __FILE__, __LINE__, name.c_str(), turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_ISRELAIS) ? 'R' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
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_ISRELAIS) {
printf ("%s:%d is relais.... %d\n", __FILE__, __LINE__, value);
server->interfaces.SetTurnout(&turnouts[i], value, value);
}
else {
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
}
jp.Clear();
jp.AddObject("turnout", _GetJSON(i));
if (network) network->ChangeListPushToAll(jp.ToString());
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;
@ -204,41 +188,20 @@ int Turnouts::Set(string name, int value) {
return 1;
};
// return -1 not found, 0 inactive 1 active
int Turnouts::Get(string name) {
int i;
int res = -1;
//
Lock();
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
if (name.compare(turnouts[i].name) == 0) {
if (turnouts[i].flags & TURNOUT_F_TURNOUT) res = 1;
else res = 0;
break;
}
}
UnLock();
return res;
}
//
// got some data from bus
void Turnouts::SetFromBus(string ifname, int addr, int value) {
int i;
JSONParse jp;
debug (0, "%s:%d Turnouts::SetFromBus Interface:%s, addr: %d, value:%d", __FILE__, __LINE__, ifname.c_str(), addr, value);
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, "%s:%d Turnout::SetFromBus Name:%s Flags:%d[%c%c%c%c]", __FILE__, __LINE__, turnouts[i].name, turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_ISRELAIS) ? 'R' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
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_INVERSE) ? 'I' : '-');
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-');
// if (value) turnouts[i].flags |= TURNOUT_F_ACTIVE;
// else turnouts[i].flags &= ~TURNOUT_F_ACTIVE;
@ -251,11 +214,10 @@ void Turnouts::SetFromBus(string ifname, int addr, int value) {
if (value) turnouts[i].flags |= TURNOUT_F_TURNOUT;
else turnouts[i].flags &= ~TURNOUT_F_TURNOUT;
}
debug (0, "%s:%d Turnout::SetFromBus Name:%s Flags:%d[%c%c%c%c]", __FILE__, __LINE__, turnouts[i].name, turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_ISRELAIS) ? 'R' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
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_INVERSE) ? 'I' : '-');
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-');
jp.AddObject("turnout", _GetJSON(i));
if(network) network->ChangeListPushToAll(jp.ToString());
@ -265,13 +227,11 @@ void Turnouts::SetFromBus(string ifname, int addr, int value) {
/*
* this loop is important: some outputs especially motors needs to be deactivated
* after a short period of time.
*/
//
// this loop is important: Turnout motors needs to be deactivated after a short time
//
void Turnouts::Loop() {
int i;
JSONParse jp;
struct timeval curtime;
gettimeofday(&curtime, NULL);
@ -279,9 +239,9 @@ void Turnouts::Loop() {
Lock();
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
if ((turnouts[i].flags & TURNOUT_F_ACTIVE) && ((turnouts[i].flags & TURNOUT_F_ISRELAIS) == 0)) {
if (turnouts[i].flags & TURNOUT_F_ACTIVE) {
//
// motor/output still active check timeout and deactivate
// 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);
@ -289,84 +249,14 @@ void Turnouts::Loop() {
// debug (0, "%s:%d timediff: %d", __FILE__, __LINE__, timediff);
if (timediff > turnouts[i].activetimeout) {
int turnout = (turnouts[i].flags & TURNOUT_F_TURNOUT) != 0 ? 1 : 0;
debug (0, "%s:%d Turnout::Loop Name:%s Flags:%d[%c%c%c%c] Turnout:%d", __FILE__, __LINE__, turnouts[i].name, turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_ISRELAIS) ? 'R' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-',
turnout);
int active = turnouts[i].flags & TURNOUT_F_TURNOUT;
if (turnouts[i].flags & TURNOUT_F_INVERSE)
server->interfaces.SetTurnout(&turnouts[i], !turnout, 0); // motor on
server->interfaces.SetTurnout(&turnouts[i], !active, 0); // motor on
else
server->interfaces.SetTurnout(&turnouts[i], turnout, 0); // motor on
server->interfaces.SetTurnout(&turnouts[i], active, 0); // motor on
turnouts[i].flags &= ~TURNOUT_F_ACTIVE;
jp.Clear();
jp.AddObject("turnout", _GetJSON(i));
if (network) network->ChangeListPushToAll(jp.ToString());
}
}
}
UnLock();
};
string Turnouts::GetName(int idx) {
string result = "";
Lock();
if (idx <= max && idx >= 0)
result = turnouts[idx].name;
UnLock();
return result;
};
int Turnouts::GetFlags(int idx) {
int result = 0;
Lock();
if (idx <= max && idx >= 0)
result = turnouts[idx].flags;
UnLock();
return result;
};
void Turnouts::SetFlags(int idx, int flags) {
JSONParse jp;
Lock();
if (idx <= max && idx >= 0) {
turnouts[idx].flags = flags;
jp.Clear();
jp.AddObject("turnout", _GetJSON(idx));
if (network) network->ChangeListPushToAll(jp.ToString());
}
UnLock();
};
int Turnouts::GetIdx(string name) {
int i;
int res = -1;
//
Lock();
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
if (name.compare(turnouts[i].name) == 0) {
res = i;
break;
}
}
UnLock();
return res;
}

@ -5,10 +5,9 @@
#include "modelbahn.h"
#include "server.h"
//
#define TURNOUT_F_INVERSE 0x0001 // inverse output
#define TURNOUT_F_ACTIVE 0x0002 // motor/output active
#define TURNOUT_F_TURNOUT 0x0004 // turnout active
#define TURNOUT_F_ISRELAIS 0x0008 // output is relais no auto off
#define TURNOUT_F_INVERSE 0x0001 // inverse output
#define TURNOUT_F_ACTIVE 0x0002 // motor active
#define TURNOUT_F_TURNOUT 0x0004 // turnout active
#define TURNOUT_DEFAULT_ACTIVETIMEOUT 250 // active timeout default value
@ -19,8 +18,6 @@ struct s_Turnout {
int flags; // setup of some flags;
int activetimeout; // time in ms // 0 will be set to DEFAULT
struct timeval activatetime; // set both to 0 for inactive
char lockedby[REFERENCENAME_LEN]; // element locked by locreference (only set by server, not by JSON/Webinterface)
} typedef Turnout;
@ -46,7 +43,6 @@ class Turnouts {
int Change(Turnout *to);
int Delete(string name);
int Set(string name, int active);
int Get(string name);
void Loop();
@ -54,11 +50,6 @@ class Turnouts {
void GetJSONAll(JSONParse *json);
Turnout GetTurnoutFromJSON(JSONParse *j);
string GetName(int idx);
int GetIdx(string name);
int GetFlags(int idx);
void SetFlags(int idx, int flags);
void SetFromBus(string name, int addr, int active);
};

@ -3,15 +3,6 @@
//
var blocks = [];
const BLOCK_F_OFF = 0x0001;
const BLOCK_F_SPLIT = 0x0002;
const BLOCK_F_SPLITPOS = 0x0004;
const BLOCK_F_SHORT = 0x0010;
const BLOCK_F_ENDSTATION = 0x0040;
const BLOCK_F_STATION = 0x0080;
const BLOCK_F_SPEEDLIMIT = 0x0100;
const BLOCK_F_ONLYCARGO = 0x0200;
const BLOCK_F_ONLYPASSENGER = 0x0400;
//
// update or add a new element
@ -21,36 +12,15 @@ function block_Update(blockdata) {
if (blockdata.name == blocks[i].name) {
blocks[i].name = blockdata.name;
blocks[i].flags = blockdata.flags;
blocks[i].lockedby = blockdata.lockedby;
blocks[i].sensor_stop_0 = blockdata.sensor_stop_0;
blocks[i].sensor_shortstop_0 = blockdata.sensor_shortstop_0;
blocks[i].sensor_slow_0 = blockdata.sensor_slow_0;
blocks[i].sensor_enter_0 = blockdata.sensor_enter_0;
blocks[i].sensor_stop_1 = blockdata.sensor_stop_1;
blocks[i].sensor_shortstop_1 = blockdata.sensor_shortstop_1;
blocks[i].sensor_slow_1 = blockdata.sensor_slow_1;
blocks[i].sensor_enter_1 = blockdata.sensor_enter_1;
blocks[i].secondblock = blockdata.secondblock;
blockdetail_setData(blocks[i]);
return;
}
}
// not found add element
//console.log ("Add Interface:" + intdata.name + "(" + intdata.host + ")");
//debug ("Add Interface:" + intdata.name + "(" + intdata.host + ")");
blocks.push ({
name: blockdata.name,
flags: blockdata.flags,
lockedby: blockdata.lockedby,
sensor_enter_0: blockdata.sensor_enter_0,
sensor_slow_0: blockdata.sensor_slow_0,
sensor_stop_0: blockdata.sensor_stop_0,
sensor_shortstop_0: blockdata.sensor_shortstop_0,
sensor_enter_1: blockdata.sensor_enter_1,
sensor_slow_1: blockdata.sensor_slow_1,
sensor_stop_1: blockdata.sensor_stop_1,
sensor_shortstop_1: blockdata.sensor_shortstop_1,
secondblock: blockdata.secondblock
flags: blockdata.flags
});
};
@ -75,90 +45,6 @@ function block_Delete(name) {
};
function block_contextmenu(name) {
let innerhtml = "";
innerhtml = "<center><label><select id=\"contextbox_loc\">";
innerhtml += "<option value=\"\"></option>";
for (var i = 0; i < locomotives.length; i++) {
if (locomotives[i].name)
innerhtml += "<option value=\""+locomotives[i].name+"\">"+locomotives[i].name+"</option>";
}
innerhtml += "</select></label><br>";
innerhtml += "<button id=\"contextbox_AsgnLU\" type=\"button\">Assign &lArr;&uArr;</button><br>";
innerhtml += "<button id=\"contextbox_AsgnRD\" type=\"button\">Assign &rArr;&dArr;</button><br>";
innerhtml += "<button id=\"contextbox_SetDLU\" type=\"button\">Go &lArr;&uArr;</button><br>";
innerhtml += "<button id=\"contextbox_SetDRD\" type=\"button\">Go &rArr;&dArr;</button><hr>";
innerhtml += "<button id=\"contextbox_Clear\" type=\"button\">Clear</button><br>";
innerhtml += "<button id=\"contextbox_Off\" type=\"button\">Off</button><hr>";
innerhtml += "<button id=\"contextbox_Close\" type=\"button\">Close</button></center>";
gContextmenuCreate(name, innerhtml);
gAddEventListener("contextbox_AsgnLU", 'click', block_ctxmenu_AssignLU);
gAddEventListener("contextbox_AsgnRD", 'click', block_ctxmenu_AssignRD);
gAddEventListener("contextbox_SetDLU", 'click', block_ctxmenu_DestinationLU);
gAddEventListener("contextbox_SetDRD", 'click', block_ctxmenu_DestinationRD);
gAddEventListener("contextbox_Clear", 'click', block_ctxmenu_Clear);
gAddEventListener("contextbox_Off", 'click', block_ctxmenu_Off);
gAddEventListener("contextbox_Close", 'click', gContextmenuClose);
};
function block_ctxmenu_DestinationLU (element, value) {
let loc = document.getElementById("contextbox_loc");
let name = document.getElementById("ConextMenuHead").innerHTML;
if (loc) {
locomotive_server_Dest(loc.value, name, 1);
}
gContextmenuClose();
};
function block_ctxmenu_DestinationRD (element, value) {
let loc = document.getElementById("contextbox_loc");
let name = document.getElementById("ConextMenuHead").innerHTML;
if (loc) {
locomotive_server_Dest(loc.value, name, 0);
}
gContextmenuClose();
};
function block_ctxmenu_AssignLU (element, value) {
let loc = document.getElementById("contextbox_loc");
let name = document.getElementById("ConextMenuHead").innerHTML;
if (loc) {
locomotive_server_Assign(loc.value, name, 1);
}
gContextmenuClose();
};
function block_ctxmenu_AssignRD (element, value) {
let loc = document.getElementById("contextbox_loc");
let name = document.getElementById("ConextMenuHead").innerHTML;
if (loc) {
locomotive_server_Assign(loc.value, name, 0);
}
gContextmenuClose();
};
function block_ctxmenu_Clear (element, value) {
let name = document.getElementById("ConextMenuHead").innerHTML;
block_server_Clear(name);
gContextmenuClose();
}
function block_ctxmenu_Off (element, value) {
let name = document.getElementById("ConextMenuHead").innerHTML;
block_server_Off(name);
gContextmenuClose();
}
//
// send new element to server
//
@ -177,101 +63,31 @@ function block_server_Del(elm) {
};
//
// send clear block
//
function block_server_Clear(blockname) {
var request = { command: "blockclear", block: blockname };
serverinout (request, serverinout_defaultCallback);
};
//
// send put block off service
//
function block_server_Off(blockname) {
var request = { command: "blockoff", block: blockname };
console.log ("send BlockOff:" + blockname);
serverinout (request, serverinout_defaultCallback);
};
//
// if create is set the name should be filled in
function blockdetail_fillsensor() {
let r = "<option value=\"\"></option>";
for (var i = 0; i < sensors.length; i++) {
if (sensors[i].name)
r += "<option value=\""+sensors[i].name+"\">"+sensors[i].name+"</option>";
};
return r;
}
function blockdetail_show(name, create) {
function blockdetail_show(name) {
var win = document.getElementById("blockdetail");
let innerHTML = " \
debug ("blockdetail_show");
if (!win) {
debug ("blockdetail_show create window");
win = gWindowCreate("blockdetail", "Block", 400, 300, " \
<div style=\"float: left\"> \
Block Name: <input id=\"blockdet_name\" style=\"width: 100\"> \
</div> <div style=\"float: right\"> \
<button id=\"blockdet_PREV\">&lt</button> \
<button id=\"blockdet_NEXT\">&gt</button> \
</div><br><hr>\
<div>\
\
<table><tr><td>\
\
<table><tr> \
<td><label><input id=\"blockdet_flagoff\" type=\"checkbox\" value=\"\" disabled>Off Service</label></td> \
<td><label><input id=\"blockdet_flagonlycargo\" type=\"checkbox\" value=\"\">Only Cargo</label></td> \
<td><label><input id=\"blockdet_flagshort\" type=\"checkbox\" value=\"\">Short</label></td> \
</tr><tr> \
<td><label><input id=\"blockdet_flagend\" type=\"checkbox\" value=\"\">End</label></td> \
<td><label><input id=\"blockdet_flagonlypassenger\" type=\"checkbox\" value=\"\">Only Passenger</label></td> \
<td><label><input id=\"blockdet_flagsplit\" type=\"checkbox\" value=\"\">Split</label></td> \
</tr><tr> \
<td><label><input id=\"blockdet_flagspeedlimit\" type=\"checkbox\" value=\"\">Speed Limit</label></td> \
<td><label><input id=\"blockdet_flagstation\" type=\"checkbox\" value=\"\">Station</label></td> \
<td><label><input id=\"blockdet_flagsplitpos\" type=\"checkbox\" value=\"\">Splitpos</label></td> \
</tr><tr> \
<td></td><td>second block:</td><td>";
innerHTML += "<input id=\"blockdet_secondblock\" style=\"width: 100\">";
innerHTML += " \
</tr></table> \
\
</td><td></td></tr></table> \
<fieldset><legend>Automatic Mode</legend><table> \
<tr><td>Lockedby:</td><td><input id=\"blockdet_lockedby\" style=\"width: 100\" disabled></td></tr>"
innerHTML += "<table><tr><td></td><td>enter</td><td>slow</td><td>shortstop</td><td>stop</td></tr>";
innerHTML += "<tr><td>Direction &rarr;&darr;:</td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_enter_0\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_slow_0\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_shortstop_0\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_stop_0\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "</tr>";
innerHTML += "<tr><td>Direction &larr;&uarr;:</td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_enter_1\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_slow_1\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_shortstop_1\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_stop_1\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "</tr></table>";
innerHTML += "</td></tr></table></fileset>\
</div> <hr>\
</div> <br> <hr>\
<div> \
<table><tr><td><table>\
</td></tr></table> </div> <hr>\
<div align=right> \
<button id=\"blockdet_SAVE\" type=\"button\">Save</button> \
<button id=\"blockdet_DELETE\" type=\"button\">Delete</button> \
<button id=\"blockdet_CLOSE\">Close</button> \
</div> \
\
";
console.log ("blockdetail_show");
if (!win) {
console.log ("blockdetail_show create window");
win = gWindowCreate("blockdetail", "Block", 500, 400, innerHTML);
");
gAddEventListener("blockdet_CLOSE", 'click', blockdetail_cb_close);
gAddEventListener("blockdet_DELETE", 'click', blockdetail_cb_delete);
@ -286,11 +102,6 @@ function blockdetail_show(name, create) {
if (name == blocks[i].name) blockdetail_setData(blocks[i]);
}
}
if (create) {
let rname = document.getElementById("blockdet_name");
if (rname.value != name) rname.value = name;
}
};
@ -344,7 +155,7 @@ function blockdetail_cb_next () {
if (i == cursel) blockdetail_setData(blocks[i]);
}
// console.log ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
// debug ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
};
@ -367,7 +178,7 @@ function blockdetail_cb_prev () {
if (i == cursel) blockdetail_setData(blocks[i]);
}
// console.log ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
// debug ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
};
@ -376,47 +187,11 @@ function blockdetail_cb_prev () {
//
function blockdetail_setData(elm) {
var name = document.getElementById("blockdet_name");
var flagoff = document.getElementById("blockdet_flagoff");
var flagshort = document.getElementById("blockdet_flagshort");
var flagsplit = document.getElementById("blockdet_flagsplit");
var flagsplitpos = document.getElementById("blockdet_flagsplitpos");
var flagend = document.getElementById("blockdet_flagend");
var flagonlycargo = document.getElementById("blockdet_flagonlycargo");
var flagonlypassenger = document.getElementById("blockdet_flagonlypassenger");
var flagstation = document.getElementById("blockdet_flagstation");
var flagspeedlimit = document.getElementById("blockdet_flagspeedlimit");
var sensor_enter_0 = document.getElementById("blockdet_sensor_enter_0");
var sensor_slow_0 = document.getElementById("blockdet_sensor_slow_0");
var sensor_stop_0 = document.getElementById("blockdet_sensor_stop_0");
var sensor_shortstop_0 = document.getElementById("blockdet_sensor_shortstop_0");
var sensor_enter_1 = document.getElementById("blockdet_sensor_enter_1");
var sensor_slow_1 = document.getElementById("blockdet_sensor_slow_1");
var sensor_stop_1 = document.getElementById("blockdet_sensor_stop_1");
var sensor_shortstop_1 = document.getElementById("blockdet_sensor_shortstop_1");
var lockedby = document.getElementById("blockdet_lockedby");
var secondblock = document.getElementById("blockdet_secondblock");
var flags = document.getElementById("blockdet_flags");
if (elm) {
if (name) name.value = elm.name;
if (flagoff) flagoff.checked = Number(elm.flags) & BLOCK_F_OFF;
if (flagshort) flagshort.checked = Number(elm.flags) & BLOCK_F_SHORT;
if (flagsplit) flagsplit.checked = Number(elm.flags) & BLOCK_F_SPLIT;
if (flagsplitpos) flagsplitpos.checked = Number(elm.flags) & BLOCK_F_SPLITPOS;
if (flagend) flagend.checked = Number(elm.flags) & BLOCK_F_ENDSTATION;
if (flagonlycargo) flagonlycargo.checked = Number(elm.flags) & BLOCK_F_ONLYCARGO;
if (flagonlypassenger) flagonlypassenger.checked = Number(elm.flags) & BLOCK_F_ONLYPASSENGER;
if (flagstation) flagstation.checked = Number(elm.flags) & BLOCK_F_STATION;
if (flagspeedlimit) flagspeedlimit.checked = Number(elm.flags) & BLOCK_F_SPEEDLIMIT;
if (sensor_enter_0) sensor_enter_0.value = elm.sensor_enter_0;
if (sensor_slow_0) sensor_slow_0.value = elm.sensor_slow_0;
if (sensor_stop_0) sensor_stop_0.value = elm.sensor_stop_0;
if (sensor_shortstop_0) sensor_shortstop_0.value = elm.sensor_shortstop_0;
if (sensor_enter_1) sensor_enter_1.value = elm.sensor_enter_1;
if (sensor_slow_1) sensor_slow_1.value = elm.sensor_slow_1;
if (sensor_stop_1) sensor_stop_1.value = elm.sensor_stop_1;
if (sensor_shortstop_1) sensor_shortstop_1.value = elm.sensor_shortstop_1;
if (secondblock) secondblock.value = elm.secondblock;
if (lockedby) lockedby.value = elm.lockedby;
if (flags) flags.value = elm.flags;
}
};
@ -428,64 +203,10 @@ function blockdetail_setData(elm) {
function blockdetail_getData() {
var res = { name: "", flags:0 };
var name = document.getElementById("blockdet_name");
var flagoff = document.getElementById("blockdet_flagoff");
var flagshort = document.getElementById("blockdet_flagshort");
var flagsplit = document.getElementById("blockdet_flagsplit");
var flagsplitpos = document.getElementById("blockdet_flagsplitpos");
var flagend = document.getElementById("blockdet_flagend");
var flagonlycargo = document.getElementById("blockdet_flagonlycargo");
var flagonlypassenger = document.getElementById("blockdet_flagonlypassenger");
var flagstation = document.getElementById("blockdet_flagstation");
var flagspeedlimit = document.getElementById("blockdet_flagspeedlimit");
var sensor_enter_0 = document.getElementById("blockdet_sensor_enter_0");
var sensor_slow_0 = document.getElementById("blockdet_sensor_slow_0");
var sensor_stop_0 = document.getElementById("blockdet_sensor_stop_0");
var sensor_shortstop_0 = document.getElementById("blockdet_sensor_shortstop_0");
var sensor_enter_1 = document.getElementById("blockdet_sensor_enter_1");
var sensor_slow_1 = document.getElementById("blockdet_sensor_slow_1");
var sensor_stop_1 = document.getElementById("blockdet_sensor_stop_1");
var sensor_shortstop_1 = document.getElementById("blockdet_sensor_shortstop_1");
var secondblock = document.getElementById("blockdet_secondblock");
var flags = document.getElementById("blockdet_flags");
if (name) res.name = name.value;
if (flagoff.checked) res.flags |= BLOCK_F_OFF;
else res.flags &= ~BLOCK_F_OFF;
if (flagshort.checked) res.flags |= BLOCK_F_SHORT;
else res.flags &= ~BLOCK_F_SHORT;
if (flagsplit.checked) res.flags |= BLOCK_F_SPLIT;
else res.flags &= ~BLOCK_F_SPLIT;
if (flagsplitpos.checked) res.flags |= BLOCK_F_SPLITPOS;
else res.flags &= ~BLOCK_F_SPLITPOS;
if (flagend.checked) res.flags |= BLOCK_F_ENDSTATION;
else res.flags &= ~BLOCK_F_ENDSTATION;
if (flagonlycargo.checked) res.flags |= BLOCK_F_ONLYCARGO;
else res.flags &= ~BLOCK_F_ONLYCARGO;
if (flagonlypassenger.checked) res.flags |= BLOCK_F_ONLYPASSENGER;
else res.flags &= ~BLOCK_F_ONLYPASSENGER;
if (flagstation.checked) res.flags |= BLOCK_F_STATION;
else res.flags &= ~BLOCK_F_STATION;
if (flagspeedlimit.checked) res.flags |= BLOCK_F_SPEEDLIMIT;
else res.flags &= ~BLOCK_F_SPEEDLIMIT;
if (sensor_enter_0) res.sensor_enter_0 = sensor_enter_0.value;
if (sensor_slow_0) res.sensor_slow_0 = sensor_slow_0.value;
if (sensor_stop_0) res.sensor_stop_0 = sensor_stop_0.value;
if (sensor_shortstop_0) res.sensor_shortstop_0 = sensor_shortstop_0.value;
if (sensor_enter_1) res.sensor_enter_1 = sensor_enter_1.value;
if (sensor_slow_1) res.sensor_slow_1 = sensor_slow_1.value;
if (sensor_stop_1) res.sensor_stop_1 = sensor_stop_1.value;
if (sensor_shortstop_1) res.sensor_shortstop_1 = sensor_shortstop_1.value;
if (secondblock) res.secondblock = secondblock.value;
if (flags) res.flags = flags.value;
return res;
};

@ -1,16 +1,4 @@
:root {
--head-bg-color: #0018ff;
--head-fg-color: #ffffff;
--bg-color: #dddddd;
--fg-color: #000000;
--contextmenu-bg-color: #b2ccb5;
--contextmenu-fg-color: #000000;
--contextmenu-head-bg-color: #10ff39;
--contextmenu-head-fg-color: #000000;
--input-bg-color: #c8c8c8;
--input-fg-color: black;
}
.GUIwindow {
float:left;
@ -18,86 +6,25 @@
margin: 1px;
padding: 0px;
position: absolute;
font-family: system-ui;
}
.GUIwindowHead {
border: 1px solid black;
background: var(--head-bg-color);
color: var(--head-fg-color);
background: blue;
color: white;
margin: 0px;
padding: 4px;
padding: 5px;
cursor: move;
text-align: center;
font-family: system-ui;
font-weight: bold;
}
.GUIwindowClient {
overflow: auto;
padding: 5px;
background-color: var(--bg-color);
color: var(--input-fg-color);
}
.GUIbutton {
background-color: white;
}
.GUIcontextmenu {
float:left;
border: 2px solid black;
margin: 1px;
padding: 0px;
position: absolute;
text-size: small;
font-family: "Liberation Sans Narrow", "Cantarell Thin", Sans;
}
.GUIcontextmenuHead {
border: 1px solid black;
background: var(--contextmenu-head-bg-color);
color: var(--contextmenu-head-fg-color);
margin: 0px;
padding: 1px;
text-align: center;
text-size: small;
font-family: "Liberation Sans Narrow", "Cantarell Thin", Sans;
font-weight: bold;
}
.GUIcontextmenuClient {
overflow: auto;
padding: 2px;
margin: 0px;
background-color: var(--contextmenu-bg-color);
color: var(--contextmenu-fg-color);
text-size: small;
font-family: system-ui;
}
ul.GUIcontextmenuElements {
list-style-type: none;
margin: 0px;
padding: 0px;
}
button {
padding: 6px 6px 6px 6px;
background-color: var(--input-bg-color);
color: var(--input-fg-color);
}
input {
border: 1px solid var(--input-fg-color);
background-color: var(--input-bg-color);
color: var(--input-fg-color);
font-family: "Lucida Console", Courier, monospace;
}
td {
color: var(--input-fg-color);
.GUIbutton {
}

@ -1,38 +1,16 @@
var MousePosX = null;
var MousePosY = null;
//
// init all variables with the class givin
$(document).ready(function() {
// console.log ("init");
// debug ("init");
$(".GUIwindow").each( function (i) {
gWindowDragElement(this);
});
document.addEventListener('mousemove', onMouseUpdate, false);
document.addEventListener('mouseenter', onMouseUpdate, false);
});
function onMouseUpdate(e) {
MousePosX = e.pageX;
MousePosY = e.pageY;
}
function getMouseX() {
return MousePosX;
}
function getMouseY() {
return MousePosY;
}
//
//
function gAddEventListener (id, eventname, callback) {
@ -41,63 +19,3 @@ function gAddEventListener (id, eventname, callback) {
if (obj) obj.addEventListener(eventname, callback);
};
//
// get the text between Text1 and Text2
function getTextBetween(fulltext, text1, text2) {
var end1 = text1.length;
var start2 = fulltext.length-text2.length;
if (end1 < start2) {
return fulltext.substr(text1.length, start2-end1);
}
else return "";
};
//
// Context Menus
function gContextmenuCreate(title, clientInnerHTML) {
let cm = document.getElementById("ContextMenu");
if (cm) {
let parent = cm.parentNode;
parent.removeChild(cm);
}
console.log("create Contextmenu:" + title);
var head = document.createElement("div");
head.setAttribute("id", "ConextMenuHead");
head.setAttribute("class", "GUIcontextmenuHead");
head.innerHTML = title;
var client = document.createElement("div");
client.setAttribute("id", "ContextMenuClient");
client.setAttribute("class", "GUIcontextmenuClient");
client.setAttribute("style", "max-height: 400px; max-width:150px;");
client.innerHTML = clientInnerHTML;
cm = document.createElement("div");
cm.setAttribute("id", "ContextMenu");
cm.setAttribute("class", "GUIcontextmenu");
cm.appendChild (head);
cm.appendChild (client);
document.body.appendChild(cm);
cm.style.top = getMouseY();
cm.style.left = getMouseX();
if (parseInt(cm.style.left) + 150 > window.innerWidth) cm.style.left = window.innerWidth - 150;
if (parseInt(cm.style.top) + 400 > window.innerHeight) cm.style.top = window.innerHeight - 400;
return cm;
};
function gContextmenuClose() {
let cm = document.getElementById("ContextMenu");
if (cm) {
let parent = cm.parentNode;
parent.removeChild(cm);
}
};

@ -0,0 +1,9 @@
function debug (t) {
var pre = document.getElementById("debug");
var div = document.getElementById("debug_div");
if (pre) pre.innerHTML = pre.innerHTML + "<br>" + t;
if (div) div.scrollTop = div.scrollHeight;
};

@ -77,7 +77,7 @@ function gWindowDragElement(elmnt) {
function gWindowCreate(id, title, sizex, sizey, clientHTML) {
var win = document.getElementById(id);
if (!win) {
console.log("create Title:" + title);
debug("create Title:" + title);
var head = document.createElement("div");
head.setAttribute("id", id+"Head");
@ -98,7 +98,7 @@ function gWindowCreate(id, title, sizex, sizey, clientHTML) {
document.body.appendChild(win);
gWindowDragElement(win);
console.log ("move to 100px from top");
debug ("move to 100px from top");
win.style.top = "100px";
}
return win;
@ -108,7 +108,7 @@ function gWindowCreate(id, title, sizex, sizey, clientHTML) {
function gWindowCreateSize(id, title, sizex, sizey) {
var win = document.getElementById(id);
if (!win) {
console.log("create Title:" + title);
debug("create Title:" + title);
var head = document.createElement("div");
head.setAttribute("id", id+"Head");
@ -129,7 +129,7 @@ function gWindowCreateSize(id, title, sizex, sizey) {
win.appendChild (client);
document.body.appendChild(win);
gWindowDragElement(win);
console.log ("move to 100px from top");
debug ("move to 100px from top");
win.style.top = "100px";
}
return win;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

@ -1,8 +1,8 @@
<html>
<meta charset="utf-8">
<head>
<title>Modelbahn</title>
<script src="jquery-3.1.0.min.js"></script>
<script src="gui/guidebug.js"></script>
<script src="gui/guiwindow.js"></script>
<script src="gui/gui.js"></script>
<script src="serverinout.js"></script>
@ -27,6 +27,7 @@
</button>
<div class="dropdown-content">
<a href="#" onclick="serverinout_Save(this);">Save</a>
<a href="#" onclick="debug_Enable(this);">Debug</a>
</div>
</div>
<div class="dropdown">
@ -38,60 +39,59 @@
<a href="#" onclick="intdetail_show(this);">Interfaces</a>
<a href="#" onclick="turndetail_show(this);">Turnouts</a>
<a href="#" onclick="locodetail_show(this);">Locomotives</a>
<a href="#" onclick="sensorlist_show(this);">Sensors</a>
<a href="#" onclick="sensordetail_show(this);">Sensors</a>
<a href="#" onclick="blockdetail_show(this);">Block</a>
</div>
</div>
<div id="infoclient" style="float:right; padding: 8px 8px;">infoclient</div>
<div id="infoserver" style="float:right; padding: 8px 8px;">infoserver</div>
<div id="infoserverstatus" style="float:right; padding: 8px 8px;">notconnected</div>
<div id="infoline" style="float:right; padding: 8px 8px;">editinfo</div>
</div>
<div class="page_side">
<button class="side_btn" id="btn-onoff" onclick="sideBtnOnOffClick(this);" value="0">
<img src="images/btnonoff.png"></button>
<br><br>
<button class="side_btn_mode" id="sidebtn-reset" onclick="sideBtnResetClick(this);" value="none">
<img src="images/btnreset.png"></button><br>
<button class="side_btn_mode" id="sidebtn-manual" onclick="sideBtnManualClick(this);" value="none">
<img src="images/btnmanual.png"></button><br>
<button class="side_btn_mode" id="sidebtn-auto" onclick="sideBtnAutoClick(this);" value="none">
<img src="images/btnauto.png"></button><br>
<br>
<button class="side_btn_cmd" id="sidebtn-close" onclick="sideBtnCloseClick(this);" value="none">
<img src="images/btnclose.png"></button><br><br>
<br><br>
<div class="page_side_edit" id="side_trackeditbuttons" style="display: none;">
<button class="side_btn_cmd side_btn_selected" id="cmd-none" onclick="sideBtnCmdClick(this);" value="none">
<div class="page_side_edit" id="side_trackedit" style="display: none;">
<button class="side_btn_mode side_btn_selected" id="mode-none" onclick="sideBtnModeClick(this);" value="none">
<img src="images/btnarrow.png"></button>
<button class="side_btn_cmd" id="cmd-track-move" onclick="sideBtnCmdClick(this);" value="move">
<button class="side_btn_mode" id="mode-move" onclick="sideBtnModeClick(this);" value="move">
<img src="images/btnmove.png"></button>
<button class="side_btn_cmd" id="cmd-track-delete" onclick="sideBtnCmdClick(this);" value="delete">
<button class="side_btn_mode" id="mode-delete" onclick="sideBtnModeClick(this);" value="delete">
<img src="images/btndelete.png"></button>
<button class="side_btn_cmd" id="cmd-track-rail" onclick="sideBtnCmdClick(this);" value="rail">
<button class="side_btn_mode" id="mode-rail" onclick="sideBtnModeClick(this);" value="rail">
<img src="images/btnrail.png"></button>
<button class="side_btn_cmd" id="cmd-track-detail" onclick="sideBtnCmdClick(this);" value="detail">
<img src="images/btnsettings.png"></button>
<button class="side_btn_mode" id="mode-turn" onclick="sideBtnModeClick(this);" value="turnout">
<img src="images/btnturnout.png"></button>
<br><br>
</div>
</div>
<div class="page_side_edit" id="side_normalbuttons" style="display: block;">
<button class="side_btn_cmd" id="sidebtn-loco" onclick="sideBtnLocoClick(this);" value="none">
<img src="images/btnloco.png"></button><br><br>
</div>
<div class="page_main" id="page_main"></div>
<div class="page_bottom" id="debug_div">
<pre id="debug"></pre>
</div>
<div class="page_main" id="page_main"></div>
<script>
function debug_Enable() {
var x = document.getElementById("debug_div");
if (x.style.display === "none") {
$(':root').css('--bottom-height', '256px');
x.style.display = "block";
} else {
$(':root').css('--bottom-height', '0px');
x.style.display = "none";
}
}
$(document).ready(function() {
var client = document.getElementById("page_main");
var canvas = trackCreate(5, 5);
var text = document.getElementById("infoserver");
var text = document.getElementById("infoline");
text.innerHTML = "---";
client.appendChild (canvas);

@ -10,7 +10,7 @@ var interfaces = [];
function interface_Update(intdata) {
for (var i = 0; i < interfaces.length; i++) {
if (intdata.name == interfaces[i].name) {
console.log ("Update Interface:" + interfaces[i].name + "(" + interfaces[i].host + ") with Interface:" + intdata.name + "(" + intdata.host + ") Flags:" + intdata.flags);
//debug ("Update Interface:" + interfaces[i].name + "(" + interfaces[i].host + ") with Interface:" + intdata.name + "(" + intdata.host + ")");
if (!(intdata.flags & 0x0001)) sideBtnOnOffMode (3); // not connected
else if ((intdata.flags & 0x0010)) sideBtnOnOffMode (3); // programming mode
@ -28,7 +28,7 @@ function interface_Update(intdata) {
}
// not found add element
//console.log ("Add Interface:" + intdata.name + "(" + intdata.host + ")");
//debug ("Add Interface:" + intdata.name + "(" + intdata.host + ")");
interfaces.push ({
name: intdata.name,
host: intdata.host,
@ -80,10 +80,10 @@ function interface_server_Del(elm) {
function intdetail_show(intname) {
var win = document.getElementById("intdetail");
console.log ("intdetail_show");
debug ("intdetail_show");
if (!win) {
console.log ("intdetail_show create window");
debug ("intdetail_show create window");
win = gWindowCreate("intdetail", "Interface", 400, 300, " \
<div style=\"float: left\"> \
Interface Name: <input id=\"intdet_name\" style=\"width: 100\"> \
@ -181,7 +181,7 @@ function intdetail_cb_next () {
if (i == cursel) intdetail_setData(interfaces[i]);
}
// console.log ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
// debug ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
};
@ -204,7 +204,7 @@ function intdetail_cb_prev () {
if (i == cursel) intdetail_setData(interfaces[i]);
}
// console.log ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
// debug ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
};

@ -1,40 +1,14 @@
body {
margin: 0px;
font-family: system-ui;
}
:root {
--top-height: 35px;
--top-height: 34px;
--side-width: 37px;
--bottom-height: 0px;
--bottom-height: 32px;
--menu-bg-color: #333;
--menu-fg-color: linen;
--track-bg: #939393;
--track-color-select: #F88;
--track-color-selectframe: #00F;
--track-border: #000;
--track-color: #BBB;
--track-color-locked: #FF0;
--track-color-closed: #F00;
--track-color-error: deeppink;
--track-text: lightblue;
--track-connector: #FFF;
--track-element-fg: #FFF;
--track-element-fgborder: #000;
--block-bg: #DDD;
--block-fg: #000;
--block-bg-locked: #FF0;
--block-fg-locked: #000;
--block-bg-closed: #800;
--block-fg-closed: #FFF;
--turnout-this: var(--track-color);
--turnout-other: #666;
--sensor-active: #0F0;
--sensor-inactive: #666;
--button-active: #0F0;
--button-inactive: #666;
}
.page_side {
@ -54,12 +28,6 @@ body {
margin: 0px 0px;
}
.side_btn_cmd {
background-color: lightgray;
padding: 0px 0px;
margin: 0px 0px;
}
.side_btn {
background-color: lightgray;
padding: 0px 0px;

@ -2,14 +2,6 @@
//
//
const LOCO_F_REVERSE = 0x0001;
const LOCO_F_CARGO = 0x0010;
const LOCO_F_CANREVERSE = 0x0020;
const LOCO_F_SHORTTRAIN = 0x0040;
const LOCO_F_AUTO = 0x0100;
const LOCO_F_AUTOSHED = 0x0200;
const LOCO_F_AUTORANDOM = 0x0400;
const LOCO_F_AUTOSTOP = 0x0800;
var locomotives = [];
@ -20,59 +12,36 @@ var locomotives = [];
function locomotive_Update(data) {
for (var i = 0; i < locomotives.length; i++) {
if (data.name == locomotives[i].name) {
var loco_name = document.getElementById("locodet_name");
console.log ("Update Locomotive:" + locomotives[i].name + " with Locomotive:" + data.name);
debug ("Update Locomotive:" + locomotives[i].name + " with Locomotive:" + data.name);
locomotives[i].name = data.name;
locomotives[i].ifname = data.ifname;
locomotives[i].addr = data.addr;
locomotives[i].stepcode = data.stepcode;
if (data.speed) locomotives[i].speed = data.speed;
locomotives[i].steps = data.steps;
locomotives[i].speed = data.speed;
locomotives[i].vmin = data.vmin;
locomotives[i].vslow = data.vslow;
locomotives[i].vmid = data.vmid;
locomotives[i].vfast = data.vfast;
locomotives[i].vmax = data.vmax;
locomotives[i].flags = data.flags;
if (data.blockassign) locomotives[i].blockassign = data.blockassign;
else locomotives[i].blockassign = "";
if (data.blockprev) locomotives[i].blockprev = data.blockprev;
else locomotives[i].blockprev = "";
if (data.blocknext) locomotives[i].blocknext = data.blocknext;
else locomotives[i].blocknext = "";
if (data.blockdest) locomotives[i].blockdest = data.blockdest;
else locomotives[i].blockdest = "";
if (data.schedway) locomotives[i].schedway = data.schedway;
else locomotives[i].schedway = "";
if (data.auto_way) locomotives[i].auto_way = data.auto_way;
if (loco_name == data.name) locodetail_setData(locomotives[i]);
lococtrl_setData(data);
return;
}
}
// not found add element
console.log ("Add Locomotive:" + data.name);
debug ("Add Locomotive:" + data.name);
locomotives.push ({
name: data.name,
ifname: data.ifname,
addr: data.addr,
stepcode: data.stepcode,
steps: data.steps,
vmin: data.vmin,
vslow: data.vslow,
speed: data.speed,
vmid: data.vmid,
vfast: data.vfast,
vmax: data.vmax,
flags: data.flags,
blockassign: data.blockassign,
blockdest: data.blockdest,
blocknext: data.blocknext,
blockprev: data.blockprev,
schedway: data.schedway,
auto_way: data.auto_way
flags: data.flags
});
};
@ -115,25 +84,6 @@ function locomotive_server_Del(elm) {
};
//
// send locomotive assignment to server (is blockname is empty clear assignment)
//
function locomotive_server_Assign(locname, blockname, reverse) {
var request = { command: "locomotiveassign", locomotive: locname, block: blockname, reverse: reverse };
serverinout (request, serverinout_defaultCallback);
};
//
// set locomotive destination to server (is blockname is empty clear assignment)
//
function locomotive_server_Dest(locname, blockname, reverse) {
var request = { command: "locomotivedestination", locomotive: locname, block: blockname, reverse: reverse };
serverinout (request, serverinout_defaultCallback);
};
//
// send delete element to server
//
@ -147,12 +97,12 @@ function locomotive_server_Set(elm) {
function locodetail_show(loconame) {
var win = document.getElementById("locodetail");
console.log ("locodetail_show");
debug ("locodetail_show");
if (!win) {
console.log ("loco_showdetail create window");
win = gWindowCreate("locodetail", "Locomotive", 450, 550,
"<div style=\"float: left\"> \
debug ("loco_showdetail create window");
win = gWindowCreate("locodetail", "Locomotive", 400, 500, " \
<div style=\"float: left\"> \
Name: <input id=\"locodet_name\" style=\"width: 100\"> \
</div> <div style=\"float: right\"> \
<button id=\"locodet_PREV\">&lt</button> \
@ -163,52 +113,20 @@ function locodetail_show(loconame) {
Adress: <input id=\"locodet_addr\" style=\"width: 50\"> \
Flags: <input id=\"locodet_flags\" style=\"width: 50\"> \
</div> <hr>\
<div><table><tr><td> \
<label><input id=\"locodet_auto\" type=\"checkbox\" value=\"\" disabled>Auto</label><br> \
<label><input id=\"locodet_autoshed\" type=\"checkbox\" value=\"\" disabled>Sheduler</label><br> \
<label><input id=\"locodet_autorandom\" type=\"checkbox\" value=\"\" disabled>Random</label><br> \
</td><td> \
<label><input id=\"locodet_short\" type=\"checkbox\" value=\"\">Short Train</label><br> \
<label><input id=\"locodet_canreverse\" type=\"checkbox\" value=\"\">Can Reverse</label><br> \
</td><td> \
<label><input id=\"locodet_cargo\" type=\"checkbox\" value=\"\">Cargo</label><br> \
</td></tr></table></div> \
\
<div> <table><tr><td> \
<fieldset><legend>Speed</legend> <table>\
<label><input id=\"locodet_reverse\" type=\"checkbox\" value=\"\">Reverse</label><br> \
<tr><td></td><td>Stop</td><td><button id=\"locodet_btnvstop\" type=\"button\" value=\"vstop\">X</button> </td></tr>\
<tr><td>Vmin:</td><td><input id=\"locodet_vmin\" style=\"width: 50\"></td><td><button id=\"locodet_btnvmin\" type=\"button\" value=\"vmin\">X</button> </td></tr>\
<tr><td>Vslow:</td><td><input id=\"locodet_vslow\" style=\"width: 50\"></td><td><button id=\"locodet_btnvslow\" type=\"button\" value=\"vslow\">X</button> </td></tr> \
<tr><td>Vmid:</td><td><input id=\"locodet_vmid\" style=\"width: 50\"></td><td><button id=\"locodet_btnvmid\" type=\"button\" value=\"vmid\">X</button> </td></tr> \
<tr><td>Vfast:</td><td><input id=\"locodet_vfast\" style=\"width: 50\"></td><td><button id=\"locodet_btnvfast\" type=\"button\" value=\"vfast\">X</button> </td></tr> \
<tr><td>Vmax:</td><td><input id=\"locodet_vmax\" style=\"width: 50\"></td><td><button id=\"locodet_btnvmax\" type=\"button\" value=\"vmax\">X</button> </td></tr> \
<tr><td>Current:</td><td><input id=\"locodet_speed\" style=\"width: 50\"></td></tr></table> \
\
</fieldset></td> \
</table></td></fieldset> \
<td> \
<fieldset><legend>Code</legend> \
<label><input type=\"radio\" id=\"locodet_DCC14\" name=\"STEPCODE\" value=\"1\">DCC14</label><br> \
<label><input type=\"radio\" id=\"locodet_DCC28\" name=\"STEPCODE\" value=\"2\">DCC28</label><br> \
<label><input type=\"radio\" id=\"locodet_DCC128\" name=\"STEPCODE\" value=\"3\">DCC128</label><br> \
</fieldset> \
\
<fieldset><legend>Block</legend><table> \
<tr><td>Assined:</td><td><input id=\"locodet_blockassign\" style=\"width: 50\" disabled></td></tr> \
<tr><td>Destination:</td><td><input id=\"locodet_blockdest\" style=\"width: 50\" disabled></td></tr> \
<tr><td>Next:</td><td><input id=\"locodet_blocknext\" style=\"width: 50\" disabled></td></tr> \
<tr><td>Prev:</td><td><input id=\"locodet_blockprev\" style=\"width: 50\" disabled></td></tr> \
<tr><td>Auto:</td><td><input id=\"locodet_auto_way\" style=\"width: 50\" disabled></td></tr> \
</table><button id=\"locodet_RESET\" type=\"button\">Reset</button> \
<button id=\"locodet_TEST\" type=\"button\">Test</button></fileset>\
\
</td></tr></table></div> \
\
<table><tr><td> \
Sched. Way: <input id=\"locodet_schedway\" style=\"width: 250\" placeholder=\"B:+:B13,W:30,B:-:B42,W:15\"> \
</td></tr></table> \
\
<hr>\
Steps: <input id=\"locodet_steps\" style=\"width: 50\"><br> \
Speed: <input id=\"locodet_speed\" style=\"width: 50\"><br> \
<label><input id=\"locodet_reverse\" type=\"checkbox\" value=\"\"> Reverse</label> \
</td></tr></table></div> <hr>\
<div align=right> \
<button id=\"locodet_SAVE\" type=\"button\">Save</button> \
<button id=\"locodet_DELETE\" type=\"button\">Delete</button> \
@ -224,15 +142,6 @@ function locodetail_show(loconame) {
gAddEventListener("locodet_btnvfast", 'click', locodetail_cb_btnmove);
gAddEventListener("locodet_btnvmax", 'click', locodetail_cb_btnmove);
gAddEventListener("locodet_reverse", 'click', locodetail_cb_reverse);
gAddEventListener("locodet_canreverse", 'click', locodetail_cb_canreverse);
gAddEventListener("locodet_short", 'click', locodetail_cb_short);
gAddEventListener("locodet_cargo", 'click', locodetail_cb_cargo);
gAddEventListener("locodet_RESET", 'click', locodetail_cb_reset);
gAddEventListener("locodet_TEST", 'click', locodetail_cb_test);
// gAddEventListener("locodet_DCC14", 'click', locodetail_cb_stepcode);
// gAddEventListener("locodet_DCC28", 'click', locodetail_cb_stepcode);
// gAddEventListener("locodet_DCC128", 'click', locodetail_cb_stepcode);
gAddEventListener("locodet_CLOSE", 'click', locodetail_cb_close);
gAddEventListener("locodet_DELETE", 'click', locodetail_cb_delete);
@ -245,7 +154,7 @@ function locodetail_show(loconame) {
//
// load default values
var res = { name: "", ifname: "", addr: "", flags: 0, steps: "",
vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100", schedway: "" };
vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100" };
locodetail_setData(res);
if (loconame) {
@ -256,6 +165,7 @@ function locodetail_show(loconame) {
};
//
// reverse selected, setup flags
function locodetail_cb_reverse () {
@ -263,81 +173,15 @@ function locodetail_cb_reverse () {
var flags = document.getElementById("locodet_flags");
if (cbreverse.checked) {
flags.value = Number(flags.value) | LOCO_F_REVERSE;
flags.value = Number(flags.value) | 1;
}
else {
flags.value = Number(flags.value) & (0xFFFF-LOCO_F_REVERSE);
flags.value = Number(flags.value) & (0xFFFF-1);
}
};
//
// canreverse selected, setup flags
function locodetail_cb_canreverse () {
var cbreverse = document.getElementById("locodet_canreverse");
var flags = document.getElementById("locodet_flags");
if (cbreverse.checked) {
flags.value = Number(flags.value) | LOCO_F_CANREVERSE;
}
else {
flags.value = Number(flags.value) & (0xFFFF-LOCO_F_CANREVERSE);
}
};
function locodetail_cb_reset (element) {
var loco = document.getElementById("locodet_name");
if (loco.value) {
var request = { command: "locomotivereset", locomotive: loco.value };
serverinout (request, serverinout_defaultCallback);
}
};
function locodetail_cb_test (element) {
var loco = document.getElementById("locodet_name");
if (loco.value) {
var request = { command: "locomotivetest", locomotive: loco.value };
serverinout (request, serverinout_defaultCallback);
}
};
//
// canreverse selected, setup flags
function locodetail_cb_short () {
var flag = document.getElementById("locodet_short");
var flags = document.getElementById("locodet_flags");
if (flag.checked) {
flags.value = Number(flags.value) | LOCO_F_SHORTTRAIN;
}
else {
flags.value = Number(flags.value) & (0xFFFF-LOCO_F_SHORTTRAIN);
}
};
//
// cargo selected, setup flags
function locodetail_cb_cargo () {
var cbcargo = document.getElementById("locodet_cargo");
var flags = document.getElementById("locodet_flags");
if (cbcargo .checked) {
flags.value = Number(flags.value) | LOCO_F_CARGO;
}
else {
flags.value = Number(flags.value) & (0xFFFF-LOCO_F_CARGO);
}
};
function locodetail_cb_btnmove () {
@ -363,7 +207,7 @@ function locodetail_cb_btnmove () {
}
locomotive_server_Set ({name: loco_name.value, speed: speed});
console.log ("Locomotive: '" + loco_name.value +"' Speed: " + speed);
debug ("Locomotive: '" + loco_name.value +"' Speed: " + speed);
};
@ -373,7 +217,6 @@ function locodetail_cb_close () {
if (win) document.body.removeChild(win);
};
//
// Callback: Delete Button
//
@ -417,7 +260,7 @@ function locodetail_cb_next () {
if (i == cursel) locodetail_setData(locomotives[i]);
}
console.log ("Cursel: " + cursel + " locomotives.lenght:" + locomotives.length);
debug ("Cursel: " + cursel + " locomotives.lenght:" + locomotives.length);
};
@ -440,7 +283,7 @@ function locodetail_cb_prev () {
if (i == cursel) locodetail_setData(locomotives[i]);
}
console.log ("Cursel: " + cursel + " locomotives.lenght:" + locomotives.length);
debug ("Cursel: " + cursel + " locomotives.lenght:" + locomotives.length);
};
@ -453,24 +296,13 @@ function locodetail_setData(elm) {
var loco_addr = document.getElementById("locodet_addr");
var loco_speed = document.getElementById("locodet_speed");
var loco_flags = document.getElementById("locodet_flags");
var loco_steps = document.getElementById("locodet_steps");
var loco_vmin = document.getElementById("locodet_vmin");
var loco_vslow = document.getElementById("locodet_vslow");
var loco_vmid = document.getElementById("locodet_vmid");
var loco_vfast = document.getElementById("locodet_vfast");
var loco_vmax = document.getElementById("locodet_vmax");
var loco_reverse = document.getElementById("locodet_reverse");
var loco_canreverse = document.getElementById("locodet_canreverse");
var loco_short = document.getElementById("locodet_short");
var loco_cargo = document.getElementById("locodet_cargo");
var loco_auto = document.getElementById("locodet_auto");
var loco_autorandom = document.getElementById("locodet_autorandom");
var loco_autoshed = document.getElementById("locodet_autoshed");
var loco_blockassign = document.getElementById("locodet_blockassign");
var loco_blockdest = document.getElementById("locodet_blockdest");
var loco_blocknext = document.getElementById("locodet_blocknext");
var loco_blockprev = document.getElementById("locodet_blockprev");
var loco_auto_way = document.getElementById("locodet_auto_way");
var loco_schedway = document.getElementById("locodet_schedway");
if (elm) {
if (loco_name) loco_name.value = elm.name;
@ -478,55 +310,18 @@ function locodetail_setData(elm) {
if (loco_flags) loco_flags.value = elm.flags;
if (loco_addr) loco_addr.value = elm.addr;
if (loco_speed) loco_speed.value = elm.speed;
if (loco_steps) loco_steps.value = elm.steps;
if (loco_vmin) loco_vmin.value = elm.vmin;
if (loco_vslow) loco_vslow.value = elm.vslow;
if (loco_vmid) loco_vmid.value = elm.vmid;
if (loco_vfast) loco_vfast.value = elm.vfast;
if (loco_vmax) loco_vmax.value = elm.vmax;
if (loco_reverse) {
if (Number(elm.flags) & LOCO_F_REVERSE) loco_reverse.checked = true;
if (Number(elm.flags) & 1) loco_reverse.checked = true;
else loco_reverse.checked = false;
}
if (loco_canreverse) {
if (Number(elm.flags) & LOCO_F_CANREVERSE) loco_canreverse.checked = true;
else loco_canreverse.checked = false;
}
if (loco_short) {
if (Number(elm.flags) & LOCO_F_SHORTTRAIN) loco_short.checked = true;
else loco_short.checked = false;
}
if (loco_cargo) {
if (Number(elm.flags) & LOCO_F_CARGO) loco_cargo.checked = true;
else loco_cargo.checked = false;
}
if (loco_auto) {
if (Number(elm.flags) & LOCO_F_AUTO) loco_auto.checked = true;
else loco_auto.checked = false;
}
if (loco_autorandom) {
if (Number(elm.flags) & LOCO_F_AUTORANDOM) loco_autorandom.checked = true;
else loco_autorandom.checked = false;
}
if (loco_autoshed) {
if (Number(elm.flags) & LOCO_F_AUTOSHED) loco_autoshed.checked = true;
else loco_autoshed.checked = false;
}
if (loco_blockassign) loco_blockassign.value = elm.blockassign;
if (loco_blockdest) loco_blockdest.value = elm.blockdest;
if (loco_blocknext) loco_blocknext.value = elm.blocknext;
if (loco_blockprev) loco_blockprev.value = elm.blockprev;
if (loco_schedway && elm.schedway) loco_schedway.value = elm.schedway;
else if (loco_shedway) loco_schedway.value = "";
if (loco_auto_way) loco_auto_way.value = elm.auto_way;
}
var codes = document.getElementsByName('STEPCODE');
for(var i = 0; i < codes.length; i++) {
// console.log ("STEPCODE: elm.stepcode: " + elm.stepcode + " i:" + i + " codes[i].value: " + codes[i].value + " codes.id: " + codes[i].id);
if(elm.stepcode == codes[i].value) codes[i].checked = true;
else codes[i].checked = false;
}
};
@ -535,355 +330,31 @@ function locodetail_setData(elm) {
// return all elements from the dialogbox
//
function locodetail_getData() {
var res = { name: "", ifname: "", addr: "", flags: 0, stepcode:"0",
vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100", schedway: "" };
var codes = document.getElementsByName('STEPCODE');
for(var i = 0; i < codes.length; i++){
if(codes[i].checked){
res.stepcode = codes[i].value;
}
}
var res = { name: "", ifname: "", addr: "", flags: 0, steps: "",
vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100" };
var loco_name = document.getElementById("locodet_name");
var loco_ifname = document.getElementById("locodet_ifname");
var loco_flags = document.getElementById("locodet_flags");
var loco_addr = document.getElementById("locodet_addr");
var loco_steps = document.getElementById("locodet_steps");
var loco_vmin = document.getElementById("locodet_vmin");
var loco_vslow = document.getElementById("locodet_vslow");
var loco_vmid = document.getElementById("locodet_vmid");
var loco_vfast = document.getElementById("locodet_vfast");
var loco_vmax = document.getElementById("locodet_vmax");
var loco_speed = document.getElementById("locodet_speed");
var loco_schedway = document.getElementById("locodet_schedway");
if (loco_name) res.name = loco_name.value;
if (loco_ifname) res.ifname = loco_ifname.value;
if (loco_flags) res.flags = loco_flags.value;
if (loco_addr) res.addr = loco_addr.value;
if (loco_steps) res.steps = loco_steps.value;
if (loco_vmin) res.vmin = loco_vmin.value;
if (loco_vslow) res.vslow = loco_vslow.value;
if (loco_vmid) res.vmid = loco_vmid.value;
if (loco_vfast) res.vfast = loco_vfast.value;
if (loco_vmax) res.vmax = loco_vmax.value;
if (loco_speed) res.speed = loco_speed.speed;
if (loco_schedway) res.schedway = loco_schedway.value;
return res;
};
// ***********************************************************************************************
// ***********************************************************************************************
// locolist: show a list of locomotives.
//
// ***********************************************************************************************
// ***********************************************************************************************
function locolist_show() {
var win = document.getElementById("locolist");
console.log ("locolist_show");
if (!win) {
console.log ("locolist_show create window");
win = gWindowCreate("locolist", "Locomotives", 400, 500, " \
<div id=\"locolist_listdiv\"> \
<ul id=\"locolist_elements\" style=\"list-style-type:none\"></ul> \
</div> \
<div align=right> \
<button id=\"locolist_CLOSE\" type=\"button\">Close</button> \
</div> \
\
");
gAddEventListener("locolist_CLOSE", 'click', locolist_cb_close);
}
var ul = document.getElementById("locolist_elements");
//
// clear list
ul.innerHTML = "";
//
// append all locomotives
for (var i = 0; i < locomotives.length; i++) {
let li = document.createElement("li");
li.appendChild(document.createTextNode(locomotives[i].name));
li.setAttribute("id", "locol_elm_"+locomotives[i].name);
ul.appendChild(li);
gAddEventListener("locol_elm_"+locomotives[i].name, 'click', locolist_clicked);
}
};
function locolist_clicked() {
var i;
console.log ("childnodes: " + this.childNodes[0].textContent);
lococtrl_show(this.childNodes[0].textContent);
};
function locolist_cb_close () {
var win = document.getElementById("locolist");
if (win) document.body.removeChild(win);
};
// ***********************************************************************************************
// ***********************************************************************************************
// locoshow: show controls for a loco loco_NAME
//
// ***********************************************************************************************
// ***********************************************************************************************
function lococtrl_show(name) {
var win = document.getElementById("lococtrl_"+name);
var i;
console.log ("lococtrl_show:" + name);
if (!win) {
console.log ("locolist_show create window");
win = gWindowCreate("lococtrl_"+name, "Loco:"+name, 600, 600, " \
<table><tr><td> \
<fieldset><legend>Speed</legend><table><tr><td align=center>\
\
<input id=\"lococtrl_"+name+"_RANGE\" name=\""+name+"\" type=\"range\" orient=\"vertical\" \
style=\"-webkit-appearance: slider-vertical; width: 10px; height: 100px;\"\
min=\"0\" value=\"0\" max=\"100\" > \
<br><button id=\"lococtrl_"+name+"_REVBTN\" type=\"button\">REV</button> \
\
</td><td><table>\
<tr><td><button id=\"lococtrl_"+name+"_btnvstop\" type=\"button\" value=\"vstop\">Stop</button> </td></tr>\
<tr><td><button id=\"lococtrl_"+name+"_btnvmin\" type=\"button\" value=\"vmin\">Min</button></td></tr>\
<tr><td><button id=\"lococtrl_"+name+"_btnvslow\" type=\"button\" value=\"vslow\">Slow</button></td></tr> \
<tr><td><button id=\"lococtrl_"+name+"_btnvmid\" type=\"button\" value=\"vmid\">Mid</button></td></tr> \
<tr><td><button id=\"lococtrl_"+name+"_btnvfast\" type=\"button\" value=\"vfast\">Fast</button></td></tr> \
<tr><td><button id=\"lococtrl_"+name+"_btnvmax\" type=\"button\" value=\"vmax\">Max</button></td></tr> \
</table></td></tr></table></fieldset> \
</td><td>\
<fieldset><legend>Control</legend><table>\
<tr> \
<td><button id=\"lococtrl_"+name+"_btnreset\" type=\"button\">R</button></td> \
<td><button id=\"lococtrl_"+name+"_btnman\" type=\"button\" value=\"vstop\">MAN</button></td> \
</tr><tr> \
<td align=center><input id=\"lococtrl_"+name+"_cbstopman\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnstopman\" type=\"button\" value=\"vstop\">A&rArr;M</button></td> \
</tr><tr> \
<td align=center><input id=\"lococtrl_"+name+"_cbauto\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnauto\" type=\"button\" value=\"vstop\">AUTO</button></td> \
</tr><tr> \
<td align=center><input id=\"lococtrl_"+name+"_cbautoshed\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnautoshed\" type=\"button\" value=\"vstop\">SHED</button></td> \
</tr><tr> \
<td align=center><input id=\"lococtrl_"+name+"_cbautorand\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnautorand\" type=\"button\" value=\"vstop\">RAND</button></td> \
</tr> \
</table></fieldset> \
</td><tr></table>\
<br><div align=right> \
<button id=\"lococtrl_"+name+"_CLOSE\" type=\"button\" value=\""+name+"\">Close</button> \
</div> \
\
");
gAddEventListener("lococtrl_"+name+"_btnvstop", 'click', lococtrl_cb_btnmove);
gAddEventListener("lococtrl_"+name+"_btnvmin", 'click', lococtrl_cb_btnmove);
gAddEventListener("lococtrl_"+name+"_btnvslow", 'click', lococtrl_cb_btnmove);
gAddEventListener("lococtrl_"+name+"_btnvmid", 'click', lococtrl_cb_btnmove);
gAddEventListener("lococtrl_"+name+"_btnvfast", 'click', lococtrl_cb_btnmove);
gAddEventListener("lococtrl_"+name+"_btnvmax", 'click', lococtrl_cb_btnmove);
gAddEventListener("lococtrl_"+name+"_btnreset", 'click', lococtrl_cb_btnreset);
gAddEventListener("lococtrl_"+name+"_btnman", 'click', lococtrl_cb_btnman);
gAddEventListener("lococtrl_"+name+"_btnstopman", 'click', lococtrl_cb_btnstopman);
gAddEventListener("lococtrl_"+name+"_btnauto", 'click', lococtrl_cb_btnauto);
gAddEventListener("lococtrl_"+name+"_btnautorand", 'click', lococtrl_cb_btnautorand);
gAddEventListener("lococtrl_"+name+"_btnautoshed", 'click', lococtrl_cb_btnautoshed);
gAddEventListener("lococtrl_"+name+"_RANGE", 'click', lococtrl_speed);
gAddEventListener("lococtrl_"+name+"_REVBTN", 'click', lococtrl_reverse);
gAddEventListener("lococtrl_"+name+"_CLOSE", 'click', lococtrl_close);
}
for (var i = 0; i < locomotives.length; i++) {
if (name == locomotives[i].name) lococtrl_setData(locomotives[i]);
}
};
function lococtrl_cb_btnreset() {
var name = getTextBetween(this.id, "lococtrl_", "_btnreset");
var request = { command: "locomotivereset", locomotive: name };
serverinout (request, serverinout_defaultCallback);
request = { command: "locomotivesetman", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
function lococtrl_cb_btnman() {
var name = getTextBetween(this.id, "lococtrl_", "_btnman");
var request = { command: "locomotivesetman", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
function lococtrl_cb_btnstopman() {
var name = getTextBetween(this.id, "lococtrl_", "_btnstopman");
var request = { command: "locomotivesetautoman", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
function lococtrl_cb_btnauto() {
var name = getTextBetween(this.id, "lococtrl_", "_btnauto");
var request = { command: "locomotivesetauto", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
function lococtrl_cb_btnautorand() {
var name = getTextBetween(this.id, "lococtrl_", "_btnautorand");
var request = { command: "locomotivesetautorand", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
function lococtrl_cb_btnautoshed() {
var name = getTextBetween(this.id, "lococtrl_", "_btnautoshed");
var request = { command: "locomotivesetautoshed", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
function lococtrl_reverse() {
var name = getTextBetween(this.id, "lococtrl_", "_REVBTN");
var reverse;
for (var i = 0; i < locomotives.length; i++) {
if (name == locomotives[i].name) {
if (locomotives[i].flags & 1) {
reverse = 0;
this.innerHTML = "FWD";
}
else {
reverse = 1;
this.innerHTML = "REV";
}
locomotive_server_Set ({name: name, reverse: reverse});
}
}
};
function lococtrl_cb_btnmove () {
var name = getTextBetween(this.id, "lococtrl_", "_btn" + this.value);
var reverse = document.getElementById("lococtrl_"+name+"_REVBTN");
var cursel = -1;
var speed = 0;
for (var i = 0; i < locomotives.length; i++) {
if (name == locomotives[i].name) cursel = i;
}
if (cursel == -1) return;
if (this.value == "vmin") speed = Number(locomotives[cursel].vmin);
if (this.value == "vslow") speed = Number(locomotives[cursel].vslow);
if (this.value == "vmid") speed = Number(locomotives[cursel].vmid);
if (this.value == "vfast") speed = Number(locomotives[cursel].vfast);
if (this.value == "vmax") speed = Number(locomotives[cursel].vmax);
if (reverse.innerHTML == "REV") speed = 0 - speed;
locomotive_server_Set ({name: name, speed: speed});
console.log ("Locomotive: '" + name +"' Speed: " + speed);
};
function lococtrl_speed() {
var name = getTextBetween(this.id, "lococtrl_", "_RANGE");
var reverse = document.getElementById("lococtrl_"+name+"_REVBTN");
let speed = this.value;
if (reverse.innerHTML == "REV") speed = 0 - speed;
console.log ("Speed Loco:'"+name+"' Speed:'"+speed+"'");
for (var i = 0; i < locomotives.length; i++) {
if (name == locomotives[i].name) {
locomotive_server_Set ({name: name, speed: speed});
}
}
};
function lococtrl_setData(data) {
var range = document.getElementById("lococtrl_"+data.name+"_RANGE");
var reverse = document.getElementById("lococtrl_"+data.name+"_REVBTN");
var cbauto = document.getElementById("lococtrl_"+data.name+"_cbauto");
var cbautorand = document.getElementById("lococtrl_"+data.name+"_cbautorand");
var cbautoshed = document.getElementById("lococtrl_"+data.name+"_cbautoshed");
var cbmanstop = document.getElementById("lococtrl_"+data.name+"_cbstopman");
var btnman = document.getElementById("lococtrl_"+data.name+"_btnman");
var btnautostop = document.getElementById("lococtrl_"+data.name+"_btnstopman");
var btnauto = document.getElementById("lococtrl_"+data.name+"_btnauto");
var btnautorand = document.getElementById("lococtrl_"+data.name+"_btnautorand");
var btnautoshed = document.getElementById("lococtrl_"+data.name+"_btnautoshed");
if (range && reverse) {
console.log ("lococtrl: " + data.name + " speed:" + data.speed + " vmax:" +
data.vmax + " flags:" + data.flags);
if (data.flags & LOCO_F_REVERSE) reverse.innerHTML = "REV";
else reverse.innerHTML = "FWD";
cbauto.checked = (data.flags & LOCO_F_AUTO);
cbautorand.checked = (data.flags & LOCO_F_AUTORANDOM);
cbautoshed.checked = (data.flags & LOCO_F_AUTOSHED);
cbmanstop.checked = (data.flags & LOCO_F_AUTOSTOP);
if (data.flags & LOCO_F_AUTOSTOP) {
btnman.disabled = false;
btnauto.disabled = true;
btnautorand.disabled = true;
btnautoshed.disabled = true;
btnautostop.disabled = true;
}
else if (data.flags & LOCO_F_AUTO) {
btnman.disabled = true;
btnautorand.disabled = false;
btnautoshed.disabled = false;
btnautostop.disabled = false;
}
else {
btnman.disabled = true;
btnautorand.disabled = true;
btnautostop.disabled = true;
btnautoshed.disabled = true;
btnauto.disabled = false;
}
range.min = 0;
if (data.vmax) range.max = data.vmax;
range.value = Math.abs(Number(data.speed));
}
};
function lococtrl_close() {
console.log ("LocoCtrl_close:" + this.value);
var win = document.getElementById("lococtrl_"+this.value);
if (win) document.body.removeChild(win);
};

@ -2,32 +2,20 @@
//
//
const RAILWAY_T_NOTHING = 0;
const RAILWAY_T_NORMAL = 1;
const RAILWAY_T_CROSSING = 2;
const RAILWAY_T_TURNOUT = 3;
const RAILWAY_T_SENSOR = 4;
const RAILWAY_T_CONNECTOR = 5;
const RAILWAY_T_BUTTON = 6;
const RAILWAY_T_TEXT = 7;
const RAILWAY_T_BLOCK = 8;
const TURNOUT_F_INVERSE = 1;
const TURNOUT_F_OUTPUTACTIVE = 2;
const TURNOUT_F_MOTORACTIVE = 2;
const TURNOUT_F_TURNOUT = 4;
const TURNOUT_F_ISRELAIS = 8;
function rwdetail_requestcallback(response) {
console.log ("rwdetail_requestcallback");
debug ("rwdetail_requestcallback");
};
function rwdetail_request(posx, posy) {
var request = {locoid: locoID, parameter1: -1, name:"Otto"};
console.log ("rwdetail_request");
debug ("rwdetail_request");
serverinout(request, rwdetail_requestcallback);
};
@ -35,24 +23,20 @@ function rwdetail_request(posx, posy) {
function rwdetail_show(posx, posy) {
var win = document.getElementById("rwdetail");
console.log ("rwdetail_show");
debug ("rwdetail_show");
if (!win) {
console.log ("rwdetail_show create window");
debug ("rwdetail_show create window");
win = gWindowCreate("rwdetail", "Railway", 400, 500, " \
<div style=\"float: left\"> \
Position: <input id=\"rwdet_X\" style=\"width: 50\" value=\"" + posx +"\"> , <input id=\"rwdet_Y\" style=\"width: 50\" value=\"" + posy +"\"> \
</div> <br> <hr>\
<div> <table><tr><td><table> \
<tr><td>Ref.Name:</td><td><input id=\"rwdet_name\" style=\"width: 100\"><button id=\"rwdet_gotoref\" type=\"button\">&nearr;</button></td></tr> \
<tr><td>Ref.Name:</td><td><input id=\"rwdet_name\" style=\"width: 100\"></td></tr> \
<tr><td>Dir:</td><td><input id=\"rwdet_dir\" style=\"width: 25\"></td></tr> \
<tr><td>Alt Dir:</td><td><input id=\"rwdet_altdir\" style=\"width: 25\"></td></tr> \
<tr><td></td><td> \
<center><canvas id=\"rwdet_canvas\" height=\""+track.scale+"\" width=\""+track.scale+"\" style=\"border:1px solid #000000;\"></center> \
</td></tr>\
<tr><td>Lockedby:</td><td><input id=\"rwdet_lockedby\" style=\"width: 100\" disabled></td></tr>\
</table><br>\
\
</table><br> \
<center><canvas id=\"rwdet_canvas\" height=\""+track.scale+"\" width=\""+track.scale+"\" style=\"border:1px solid #000000;\"></center> <br>\
</td><td> \
<fieldset><legend>Type</legend> \
Type: <input id=\"rwdet_type\" style=\"width: 25\"><br> \
@ -76,7 +60,6 @@ function rwdetail_show(posx, posy) {
\
");
gAddEventListener("rwdet_gotoref", 'click', rwdetail_cb_gotoref);
gAddEventListener("rwdet_dir", 'change', rwdetail_cb_dirchange);
gAddEventListener("rwdet_type", 'change', rwdetail_cb_typechange);
gAddEventListener("rwdet_altdir", 'change', rwdetail_cb_dirchange);
@ -101,31 +84,10 @@ function rwdetail_show(posx, posy) {
y.value = posy;
}
console.log ("rwdetail_show track dimensions: " + track.size.x + "," + track.size.y + " Position: " + posx + "," + posy + " idx:" + (posx + posy * track.size.x));
rwdetail_setData({type: 0, x: posx, y: posy, dir: 0, altdir: 0, name: ""});
if (track.elements[posx + posy * track.size.x]) {
console.log ("rwdetail_show element found.");
rwdetail_setData(track.elements[posx + posy * track.size.x]);
}
else console.log ("rwdetail_show element NOT found.");
};
function rwdetail_cb_gotoref () {
var type = document.getElementById("rwdet_type");
var name = document.getElementById("rwdet_name");
console.log ("Name:" + name.value + " Type:" + type.value);
switch(Number(type.value)) {
case RAILWAY_T_BUTTON: turndetail_show(name.value, true); break; // button
case RAILWAY_T_TURNOUT: turndetail_show(name.value, true); break; // turnout
case RAILWAY_T_SENSOR: sensordetail_show(name.value, true); break; // sensor
case RAILWAY_T_BLOCK: blockdetail_show(name.value, true); break; // block
default: break;
}
};
function rwdetail_cb_dirchange () {
@ -216,14 +178,12 @@ function rwdetail_setData(rw) {
var type = document.getElementById("rwdet_type");
var dir = document.getElementById("rwdet_dir");
var altdir = document.getElementById("rwdet_altdir");
var lockedby = document.getElementById("rwdet_lockedby");
if (rw) {
name.value = rw.name;
type.value = rw.type;
dir.value = rw.dir;
altdir.value = rw.altdir;
lockedby.value = rw.lockedby;
}
rwdetail_cb_typechange();
@ -235,23 +195,10 @@ function rw_Click(x,y) {
var idx = x + y * track.size.x;
if (track.elements[idx]) {
//
// Turnout?
if (track.elements[idx].type == RAILWAY_TURNOUT) {
if (track.elements[idx].name != "") {
if (turnout_IsTurnoutActive(track.elements[idx].name)) {
turnout_server_Activate(track.elements[idx].name, 0);
}
else {
turnout_server_Activate(track.elements[idx].name, 1);
}
}
}
//
// Button
else if (track.elements[idx].type == RAILWAY_T_BUTTON) {
// Button or Turnout?
if (track.elements[idx].type == RAILWAY_TURNOUT || track.elements[idx].type == RAILWAY_BUTTON) {
if (track.elements[idx].name != "") {
if (turnout_IsOutputActive(track.elements[idx].name)) {
if (turnout_IsActive(track.elements[idx].name)) {
turnout_server_Activate(track.elements[idx].name, 0);
}
else {
@ -262,39 +209,10 @@ function rw_Click(x,y) {
//
// Sensor
else if (track.elements[idx].type == RAILWAY_SENSOR) {
if (track.elements[idx].type == RAILWAY_SENSOR) {
if (track.elements[idx].name != "") {
sensor_contextmenu(track.elements[idx].name);
}
}
//
// Block
else if (track.elements[idx].type == RAILWAY_BLOCK) {
block_contextmenu(track.elements[idx].name);
}
else if (y > 0 && track.elements[idx].type == RAILWAY_NORMAL && track.elements[idx].dir == 1 &&
track.elements[x + (y-1)*track.size.x].type == RAILWAY_BLOCK) {
block_contextmenu(track.elements[x + (y-1)*track.size.x].name)
}
else if (y < track.size.y && track.elements[idx].type == RAILWAY_NORMAL && track.elements[idx].dir == 1 &&
track.elements[x + (y+1)*track.size.x].type == RAILWAY_BLOCK) {
block_contextmenu(track.elements[x + (y+1)*track.size.x].name)
}
else if (x > 0 && track.elements[idx].type == RAILWAY_NORMAL && track.elements[idx].dir == 2 &&
track.elements[(x-1) + y*track.size.x].type == RAILWAY_BLOCK) {
block_contextmenu(track.elements[(x-1) + y*track.size.x].name)
}
else if (x < track.size.x && track.elements[idx].type == RAILWAY_NORMAL && track.elements[idx].dir == 2 &&
track.elements[(x+1) + y*track.size.x].type == RAILWAY_BLOCK) {
block_contextmenu(track.elements[(x+1) + y*track.size.x].name)
}
//
//
else if (track.elements[idx].type == RAILWAY_NORMAL) {
// track_selectsegment(x, y);
}
}
};
@ -314,7 +232,7 @@ var turnouts = [];
function turnout_Update(data) {
for (var i = 0; i < turnouts.length; i++) {
if (data.name == turnouts[i].name) {
console.log ("Update turnout:" + turnouts[i].name + " with turnout:" + data.name + " Flags:" + data.flags);
debug ("Update turnout:" + turnouts[i].name + " with turnout:" + data.name);
turnouts[i].name = data.name;
turnouts[i].ifname = data.ifname;
turnouts[i].addr = data.addr;
@ -324,7 +242,7 @@ function turnout_Update(data) {
}
// not found add element
console.log ("Add turnout:" + data.name + " Flags:" + data.flags);
debug ("Add turnout:" + data.name);
turnouts.push ({
name: data.name,
ifname: data.ifname,
@ -337,7 +255,7 @@ function turnout_Update(data) {
//
// return if the turnout is active or not
//
function turnout_IsTurnoutActive(name) {
function turnout_IsActive(name) {
for (var i = 0; i < turnouts.length; i++) {
if (name == turnouts[i].name) {
if (turnouts[i].flags & TURNOUT_F_TURNOUT) return 1
@ -348,17 +266,6 @@ function turnout_IsTurnoutActive(name) {
};
function turnout_IsOutputActive(name) {
for (var i = 0; i < turnouts.length; i++) {
if (name == turnouts[i].name) {
if (turnouts[i].flags & TURNOUT_F_OUTPUTACTIVE) return 1
else return 0;
}
}
return 0;
}
//
// delete element from the list
// in arrays we can not delete just an element, so we create a new one
@ -406,13 +313,13 @@ function turnout_server_Activate(name, onoff) {
function turndetail_show(turnname, create) {
function turndetail_show(turnname) {
var win = document.getElementById("turndetail");
console.log ("turndetail_show");
debug ("turndetail_show");
if (!win) {
console.log ("turndetail_show create window");
debug ("turndetail_show create window");
win = gWindowCreate("turndetail", "Turnout", 400, 500, " \
<div style=\"float: left\"> \
Name: <input id=\"turndet_name\" style=\"width: 100\"> \
@ -426,8 +333,6 @@ function turndetail_show(turnname, create) {
<tr><td>Flags:</td><td><input id=\"turndet_flags\" style=\"width: 50\"></td></tr> \
</table> </td><td> \
<label><input id=\"turndet_inverse\" type=\"checkbox\" value=\"\"> Inverse</label><br>\
<label><input id=\"turndet_output\" type=\"checkbox\" value=\"\"> Output Active</label><br>\
<label><input id=\"turndet_relais\" type=\"checkbox\" value=\"\"> Is Relais</label><br>\
<label><input id=\"turndet_active\" type=\"checkbox\" value=\"\"><dfn title=\"save first\"> Active</dfn></label>\
\
</td></tr></table></div> <hr>\
@ -441,8 +346,6 @@ function turndetail_show(turnname, create) {
gAddEventListener("turndet_inverse", 'click', turndetail_cb_inverse);
gAddEventListener("turndet_active", 'click', turndetail_cb_active);
gAddEventListener("turndet_output", 'click', turndetail_cb_output);
gAddEventListener("turndet_relais", 'click', turndetail_cb_relais);
gAddEventListener("turndet_CLOSE", 'click', turndetail_cb_close);
gAddEventListener("turndet_DELETE", 'click', turndetail_cb_delete);
@ -458,12 +361,6 @@ function turndetail_show(turnname, create) {
if (turnname == turnouts[i].name) turndetail_setData(turnouts[i]);
}
}
if (create) {
let rname = document.getElementById("turndet_name");
if (rname.value != turnname && rname.value == "") rname.value = turnname;
}
};
@ -502,34 +399,6 @@ function turndetail_cb_active () {
};
//
// output
function turndetail_cb_output () {
var cb = document.getElementById("turndet_output");
var flags = document.getElementById("turndet_flags");
var name = document.getElementById("turndet_name");
if (cb.checked)
flags.value = Number(flags.value) | TURNOUT_F_OUTPUTACTIVE;
else
flags.value = Number(flags.value) & (0xFFFF-TURNOUT_F_OUTPUTACTIVE);
};
//
// isrelais
function turndetail_cb_relais () {
var cb = document.getElementById("turndet_relais");
var flags = document.getElementById("turndet_flags");
var name = document.getElementById("turndet_name");
if (cb.checked)
flags.value = Number(flags.value) | TURNOUT_F_ISRELAIS;
else
flags.value = Number(flags.value) & (0xFFFF-TURNOUT_F_ISRELAIS);
};
function turndetail_cb_close () {
var win = document.getElementById("turndetail");
@ -580,7 +449,7 @@ function turndetail_cb_next () {
if (i == cursel) turndetail_setData(turnouts[i]);
}
// console.log ("Cursel: " + cursel + " turnouts.lenght:" + turnouts.length);
// debug ("Cursel: " + cursel + " turnouts.lenght:" + turnouts.length);
};
@ -603,7 +472,7 @@ function turndetail_cb_prev () {
if (i == cursel) turndetail_setData(turnouts[i]);
}
// console.log ("Cursel: " + cursel + " turnouts.lenght:" + turnouts.length);
// debug ("Cursel: " + cursel + " turnouts.lenght:" + turnouts.length);
};
@ -617,8 +486,6 @@ function turndetail_setData(elm) {
var turnflags = document.getElementById("turndet_flags");
var cbinverse = document.getElementById("turndet_inverse");
var cbactive = document.getElementById("turndet_active");
var cbrelais = document.getElementById("turndet_relais");
var cboutput = document.getElementById("turndet_output");
if (elm) {
if (turnname) turnname.value = elm.name;
@ -626,21 +493,13 @@ function turndetail_setData(elm) {
if (turnaddr) turnaddr.value = elm.addr;
if (turnflags) turnflags.value = elm.flags;
if (cbinverse) {
if (Number(elm.flags) & TURNOUT_F_INVERSE) cbinverse.checked = true;
if (Number(elm.flags) & 1) cbinverse.checked = true;
else cbinverse.checked = false;
}
if (cbactive) {
if (Number(elm.flags) & TURNOUT_F_TURNOUT) cbactive.checked = true;
if (Number(elm.flags) & 2) cbactive.checked = true;
else cbactive.checked = false;
}
if (cboutput) {
if (Number(elm.flags) & TURNOUT_F_OUTPUTACTIVE) cboutput.checked = true;
else cboutput.checked = false;
}
if (cbrelais) {
if (Number(elm.flags) & TURNOUT_F_ISRELAIS) cbrelais.checked = true;
else cbrelais.checked = false;
}
}
};

@ -14,7 +14,7 @@ var sensors = [];
function sensor_Update(sdata) {
for (var i = 0; i < sensors.length; i++) {
if (sdata.name == sensors[i].name) {
console.log ("Update Sensor:" + sensors[i].name + " with Sensor:" + sdata.name);
debug ("Update Sensor:" + sensors[i].name + " with Sensor:" + sdata.name);
sensors[i].name = sdata.name;
sensors[i].ifname = sdata.ifname;
sensors[i].addr = sdata.addr;
@ -24,7 +24,7 @@ function sensor_Update(sdata) {
}
// not found add element
console.log ("Add Sensor:" + sdata.name);
debug ("Add Sensor:" + sdata.name);
sensors.push ({
name: sdata.name,
ifname: sdata.ifname,
@ -88,13 +88,14 @@ function sensor_IsActive(name) {
function sensordetail_show(name, create) {
function sensordetail_show(name) {
var win = document.getElementById("sensordetail");
console.log ("sensordetail_show");
debug ("sensordetail_show");
if (!win) {
console.log ("sensordetail_show create window");
debug ("sensordetail_show create window");
win = gWindowCreate("sensordetail", "Sensor", 400, 300, " \
<div style=\"float: left\"> \
Sensor Name: <input id=\"sensor_name\" style=\"width: 100\"> \
@ -128,12 +129,6 @@ function sensordetail_show(name, create) {
if (name == sensors[i].name) sensordetail_setData(sensors[i]);
}
}
if (create) {
let rname = document.getElementById("sensor_name");
if (rname.value != name && rname.value == "") rname.value = name;
}
};
@ -187,7 +182,7 @@ function sensordetail_cb_next () {
if (i == cursel) sensordetail_setData(sensors[i]);
}
console.log ("Cursel: " + cursel + " sensors.lenght:" + sensors.length);
debug ("Cursel: " + cursel + " sensors.lenght:" + sensors.length);
};
@ -210,7 +205,7 @@ function sensordetail_cb_prev () {
if (i == cursel) sensordetail_setData(sensors[i]);
}
console.log ("Cursel: " + cursel + " sensors.lenght:" + sensors.length);
debug ("Cursel: " + cursel + " sensors.lenght:" + sensors.length);
};
@ -251,122 +246,3 @@ function sensordetail_getData() {
return res;
};
// ***********************************************************************************************
// ***********************************************************************************************
// sensorlist: show a list of sensors.
//
// ***********************************************************************************************
// ***********************************************************************************************
function sensorlist_show() {
var win = document.getElementById("sensorlist");
console.log ("sensorlist_show");
if (!win) {
console.log ("sensorlist_show create window");
win = gWindowCreate("sensorlist", "Sensors", 400, 500, " \
<div id=\"sensorlist_listdiv\"> \
<ul id=\"sensorlist_elements\" style=\"list-style-type:none\"></ul> \
</div> \
<div align=right> \
<button id=\"sensorlist_CLOSE\" type=\"button\">Close</button> \
</div> \
\
");
gAddEventListener("sensorlist_CLOSE", 'click', sensorlist_cb_close);
}
var ul = document.getElementById("sensorlist_elements");
//
// sort list
var ssorted = new Array();
for (var i = 0; i < sensors.length; i++) {
ssorted.push(sensors[i].name);
}
ssorted.sort();
//
// append all sensors
for (var i = 0; i < ssorted.length; i++) {
let li = document.createElement("li");
li.appendChild(document.createTextNode(ssorted[i]));
li.setAttribute("id", "sensor_elm_"+ssorted[i]);
ul.appendChild(li);
gAddEventListener("sensor_elm_"+ssorted[i], 'click', sensorlist_clicked);
}
};
function sensorlist_clicked() {
var i;
console.log ("childnodes: " + this.childNodes[0].textContent);
sensordetail_show(this.childNodes[0].textContent);
};
function sensorlist_cb_close () {
var win = document.getElementById("sensorlist");
if (win) document.body.removeChild(win);
};
// ***********************************************************************************************
// ***********************************************************************************************
// sensor contextmenu: show a context menu for the sensor
// this is only if the INTERFACE name is set tu DEBUG
// ***********************************************************************************************
// ***********************************************************************************************
function sensor_contextmenu(name) {
let innerhtml = "";
for (var i = 0; i < sensors.length; i++) {
if (name == sensors[i].name) {
if (sensors[i].ifname == "DEBUG") {
innerhtml = "<center>";
innerhtml += "<button id=\"contextbox_On\" type=\"button\">Set On</button><br>";
innerhtml += "<button id=\"contextbox_Off\" type=\"button\">Set Off</button><br>";
innerhtml += "<button id=\"contextbox_Close\" type=\"button\">Close</button></center>";
gContextmenuCreate(name, innerhtml);
gAddEventListener("contextbox_On", 'click', sensor_ctxmenu_On);
gAddEventListener("contextbox_Off", 'click', sensor_ctxmenu_Off);
gAddEventListener("contextbox_Close", 'click', gContextmenuClose);
}
}
}
};
function sensor_ctxmenu_On (element, value) {
let name = document.getElementById("ConextMenuHead").innerHTML;
sensor_server_setactive(name, "1");
gContextmenuClose();
}
function sensor_ctxmenu_Off (element, value) {
let name = document.getElementById("ConextMenuHead").innerHTML;
sensor_server_setactive(name, "0");
gContextmenuClose();
}
//
// send sensor activate and deactivate to server
//
function sensor_server_setactive(name, value) {
var request = { command: "sensorSetActive", sensor: name, enabled: value };
console.log ("send sensor active:" + name);
serverinout (request, serverinout_defaultCallback);
};

@ -24,30 +24,38 @@ function serverinout(request, callback) {
request.sid = sessionID;
request.rid = randomID;
// e.preventDefault();
senddata = JSON.stringify(request);
// debug('serverinout: send request:' + senddata);
$.ajax({
type: "POST",
// url: '/modelbahn/serverinout.php',
url: '/cgi-bin/modelbahn-cgi',
data: senddata,
success: function(response)
{
var jsonData = {};
// ENABLE LATER try {
jsonData = JSON.parse(response);
if (jsonData.success == "1")
{
var clientstatus = document.getElementById("infoclient");
clientstatus.innerHTML = "connected";
var serverstatus = document.getElementById("infoserverstatus");
serverstatus.innerHTML = "connected";
callback(jsonData);
}
else
{
var clientstatus = document.getElementById("infoclient");
clientstatus.innerHTML = "-trying-";
var serverstatus = document.getElementById("infoserverstatus");
serverstatus.innerHTML = "-trying-";
}
// ENABLE LATER } catch(err) {
// ENABLE LATER var serverstatus = document.getElementById("infoserverstatus");
// ENABLE LATER serverstatus.innerHTML = "-error-";
// ENABLE LATER }
},
error: function(error) {
var status = document.getElementById("infoclient");
status.innerHTML = "ajax error";
var serverstatus = document.getElementById("infoserverstatus");
serverstatus.innerHTML = "ajax error";
}
});
};
@ -84,28 +92,22 @@ function serverinout_Save(data) {
function serverinout_defaultCallback(data) {
// if (data.changes) if (data.changes.length > 0) debug ("From Server :" + JSON.stringify(data));
if (data.info) {
}
if (data.sid && data.rid) {
//
// valid data from server
if (data.rid == randomID && data.sid == sessionID) {
//
// infoline
if (data.serverstatus) {
var text = document.getElementById("infoserver");
text.innerHTML = data.serverstatus;
if (data.serverstatus == "Mode Reset") sideBtnModeClick("sidebtn-reset");
if (data.serverstatus == "Mode Manual") sideBtnModeClick("sidebtn-manual");
if (data.serverstatus == "Mode Auto") sideBtnModeClick("sidebtn-auto");
}
//
// loop through all the changes
if (data.changes) {
for (var i = 0; i < data.changes.length; i++) {
//
// Infoline changes
// infoline
if (data.changes[i].infoline) {
console.log ("Info:" + data.changes[i].infoline);
var text = document.getElementById("infoline");
text.innerHTML = data.changes[i].infoline;
}
//
@ -172,22 +174,6 @@ function serverinout_defaultCallback(data) {
if (data.changes[i].sensordelete) {
sensor_Delete(data.changes[i].sensordelete);
}
//
// Block changes
if (data.changes[i].blocks) {
for (var j = 0; j < data.changes[i].blocks.length; j++) {
block_Update(data.changes[i].blocks[j]);
}
}
if (data.changes[i].block) {
console.log ("update Block:"+ data.changes[i].block.name + " Flags:" + data.changes[i].block.flags);
block_Update(data.changes[i].block);
}
if (data.changes[i].blockdelete) {
block_Delete(data.changes[i].blockdelete);
}
}
trackDraw();
}
@ -197,16 +183,17 @@ function serverinout_defaultCallback(data) {
else if (data.rid == randomID && data.sid > 0) {
// we got a new sessionID --> request track data
if (sessionID == 0) {
debug ("setup session ID");
sessionID = data.sid;
serverinout( {command: "getall" }, serverinout_defaultCallback);
}
}
else {
console.log ("ERROR: serverinout_defaultCallback");
debug ("ERROR: serverinout_defaultCallback");
}
}
else {
console.log ("ERROR: serverinout_defaultCallback no data.sid && data.rid");
debug ("ERROR: serverinout_defaultCallback no data.sid && data.rid");
}
};
@ -220,7 +207,7 @@ function serverinout_AutoUpdateCallback(data) {
function serverinout_AutoUpdate() {
// console.log ("serverinout_AutoUpdate");
// debug ("serverinout_AutoUpdate");
if (request_running == 0) {
request_running = 0;
serverinout({}, serverinout_defaultCallback);

@ -1,8 +1,4 @@
<?php
/*
* This code is not used anymore. PHP is just too slow. We went back to the cgi-bin interface
*/
session_start();

@ -7,20 +7,17 @@ const SIDE_DISPLAY_NONE = 1;
const SIDE_DISPLAY_EDITTRACK = 2;
function side_Display(type) {
var side_track = document.getElementById("side_trackeditbuttons");
var side_normal = document.getElementById("side_normalbuttons");
var btn = document.getElementById("cmd-none");
var x = document.getElementById("side_trackedit");
var btn = document.getElementById("mode-none");
console.log ("side_display(" + type +")");
debug ("side_display(" + type +")");
if (type == SIDE_DISPLAY_EDITTRACK) {
side_normal.style.display = "none";
side_track.style.display = "block";
x.style.display = "block";
}
else {
sideBtnCmdClick(btn);
side_track.style.display = "none";
side_normal.style.display = "block";
sideBtnModeClick(btn);
x.style.display = "none";
}
}
@ -31,6 +28,7 @@ function side_Display(type) {
//
// value 0-off, 1-on, 2-stop, 3-shortciruit
function sideBtnOnOffClick (obj) {
side_Display(SIDE_DISPLAY_NONE);
if (obj.value == 0) {
serverinout_Power(1);
}
@ -69,13 +67,8 @@ function sideBtnOnOffMode (mode) {
// deselect all elements and select new one
//
function sideBtnModeClick (obj) {
let id;
if (obj.id) id = obj.id;
else id = obj;
$('.side_btn_mode').each(function(i, objiter) {
if (id == objiter.id) {
if (obj.id == objiter.id) {
objiter.className = "side_btn_mode side_btn_selected";
}
else {
@ -85,64 +78,6 @@ function sideBtnModeClick (obj) {
};
//
// deselect all elements and select new one
//
function sideBtnCmdClick (obj) {
$('.side_btn_cmd').each(function(i, objiter) {
if (obj.id == objiter.id) {
objiter.className = "side_btn_cmd side_btn_selected";
}
else {
objiter.className = "side_btn_cmd";
}
});
};
//
// show a list of locomotives
//
function sideBtnLocoClick () {
locolist_show();
};
//
// close buttons to default
//
function sideBtnCloseClick () {
side_Display(SIDE_DISPLAY_NONE);
};
//
// send sensor and turnout reset to server.
//
function sideBtnResetClick () {
var request = { command: "serverreset" };
serverinout (request, serverinout_defaultCallback);
};
//
// set server to manual mode
//
function sideBtnManualClick () {
var request = { command: "servermanual" };
serverinout (request, serverinout_defaultCallback);
};
//
// send sensor and turnout reset to server.
//
function sideBtnAutoClick () {
var request = { command: "serverauto" };
serverinout (request, serverinout_defaultCallback);
};
function sideBtnModeGet () {
var i, selected = "";
@ -152,18 +87,8 @@ function sideBtnModeGet () {
if (objiter.className == "side_btn_mode side_btn_selected") selected = objiter.id;
});
return selected;
};
function sideBtnCmdGet () {
var i, selected = "";
i = 0;
$('.side_btn_cmd').each(function(j, objiter) {
i++;
if (objiter.className == "side_btn_cmd side_btn_selected") selected = objiter.id;
});
// debug ("Selected: '" + selected + "'");
return selected;
};

@ -3,7 +3,7 @@
//
function testwinbtnclick() {
console.log ("Test Button");
debug ("Test Button");
locodetail_show("");
}

@ -14,18 +14,14 @@ const RAILWAY_BLOCK = 8;
var track = {
size: {x: -1, y: -1},
scale: 32,
scale: 24,
dbuf: {},
elements: []
};
// trackMouse.step = 0 normal
// trackMouse.step = 1 destination
var trackMouse = {
pos: {x: -1, y: -1, subx: 0.5, suby: 0.5},
down: {x :-1 , y: -1, subx: 0.5, suby: 0.5},
rect: {x1: -1, x2: -1, y1: -1, y2: -1},
step: 0
down: {x :-1 , y: -1, subx: 0.5, suby: 0.5}
};
@ -100,21 +96,13 @@ function trackDrawTrack(ctx, pos, dirtype) {
}
}
function cssVar(name,value){
if(name[0]!='-') name = '--'+name //allow passing with or without --
if(value) document.documentElement.style.setProperty(name, value)
return getComputedStyle(document.documentElement).getPropertyValue(name);
}
function trackDrawElement(ctx, element, mode) {
var dx = 0, dy = 0;
var modcol = cssVar('--track-color');
var modcol = "#B0B0B0";
if (element) {
if (mode == 1) modcol = cssVar('--track-color-select');
if (mode == 1) modcol = "#FF0000";
if (element.type) {
if (element.type == RAILWAY_TURNOUT) {
@ -123,52 +111,26 @@ function trackDrawElement(ctx, element, mode) {
var dir = element.dir;
var altdir = element.altdir;
if (element.name != "") if (turnout_IsTurnoutActive(element.name)) {
// console.log ("draw element:" + element.name + " isActive:" + turnout_IsActive(element.name));
if (element.name != "") if (turnout_IsActive(element.name)) {
// debug ("draw element:" + element.name + " isActive:" + turnout_IsActive(element.name));
altdir = element.dir;
dir = element.altdir;
}
ctx.lineWidth = 4;
ctx.setLineDash([0,0]);
if (element.lockedby && element.lockedby != "")
ctx.strokeStyle = cssVar('--track-color-locked');
else
ctx.strokeStyle = ctx.strokeStyle = cssVar('--turnout-this');
ctx.strokeStyle = modcol;
trackDrawTrack (ctx, {x: element.x, y: element.y}, dir);
ctx.setLineDash([0,0]);
if (element.name == "") ctx.strokeStyle = cssVar('--track-color-error');
else ctx.strokeStyle = cssVar('--turnout-other');
if (element.name == "") ctx.strokeStyle = "DeepPink";
else ctx.strokeStyle = "DimGray";
trackDrawTrack (ctx, {x: element.x, y: element.y}, altdir);
}
else if (element.type == RAILWAY_BUTTON) {
let bi;
ctx.beginPath();
ctx.lineWidth = 2;
ctx.setLineDash([0,0]);
ctx.strokeStyle = cssVar('--button-inactive');
for (bi = 0; bi < turnouts.length; bi++) {
if (turnouts[bi].name == element.name) {
if ((turnouts[bi].flags & TURNOUT_F_OUTPUTACTIVE) != 0)
ctx.strokeStyle = cssVar('--button-active');
}
}
ctx.moveTo((element.x+0.1) * track.scale, (element.y+0.1) * track.scale);
ctx.lineTo((element.x+0.9) * track.scale, (element.y+0.1) * track.scale);
ctx.lineTo((element.x+0.9) * track.scale, (element.y+0.9) * track.scale);
ctx.lineTo((element.x+0.1) * track.scale, (element.y+0.9) * track.scale);
ctx.lineTo((element.x+0.1) * track.scale, (element.y+0.1) * track.scale);
ctx.stroke();
}
else if (element.type == RAILWAY_NORMAL || element.type == RAILWAY_SENSOR || element.type == RAILWAY_BLOCK) {
else if (element.type == RAILWAY_NORMAL || element.type == RAILWAY_SENSOR) {
//
// normal
ctx.lineWidth = 2;
ctx.setLineDash([0,0]);
ctx.strokeStyle = modcol;
if (element.lockedby && element.lockedby != "")
ctx.strokeStyle = cssVar('--track-color-locked');
trackDrawTrack (ctx, {x: element.x, y: element.y}, element.dir);
}
else if (element.type == RAILWAY_CROSSING) {
@ -177,8 +139,6 @@ function trackDrawElement(ctx, element, mode) {
ctx.lineWidth = 2;
ctx.setLineDash([0,0]);
ctx.strokeStyle = modcol;
if (element.lockedby && element.lockedby != "")
ctx.strokeStyle = cssVar('--track-color-locked');
trackDrawTrack (ctx, {x: element.x, y: element.y}, element.dir);
trackDrawTrack (ctx, {x: element.x, y: element.y}, element.altdir);
}
@ -186,11 +146,11 @@ function trackDrawElement(ctx, element, mode) {
ctx.font = "14px Arial";
ctx.textAlign = "left";
if (element.name != "") {
ctx.fillStyle = cssVar('--track-text');
ctx.fillStyle = "lightblue";
ctx.fillText(element.name, (element.x+0.5) * track.scale, 6+(element.y+0.5) * track.scale);
}
else {
ctx.fillStyle = cssVar('--track-color-error');
ctx.fillStyle = "DeepPink";
ctx.fillText("------", (element.x+0.5) * track.scale, (element.y+0.5) * track.scale);
}
}
@ -198,11 +158,11 @@ function trackDrawElement(ctx, element, mode) {
ctx.font = "bold 12px Arial";
ctx.textAlign = "center";
if (element.name != "") {
ctx.fillStyle = cssVar('--track-connector');
ctx.fillStyle = "#FFFFFF";
ctx.fillText(element.name, (element.x+0.5) * track.scale, 6+(element.y+0.5) * track.scale);
}
else {
ctx.fillStyle = cssVar('--track-color-error');
ctx.fillStyle = "DeepPink";
ctx.fillText("------", (element.x+0.5) * track.scale, (element.y+0.5) * track.scale);
}
}
@ -210,7 +170,7 @@ function trackDrawElement(ctx, element, mode) {
ctx.beginPath();
ctx.lineWidth = 2;
ctx.setLineDash([0,0]);
ctx.strokeStyle = cssVar('--track-color-error');
ctx.strokeStyle = "DeepPink";
ctx.moveTo((element.x+0.25) * track.scale, (element.y+0.25) * track.scale);
ctx.lineTo((element.x+0.75) * track.scale, (element.y+0.75) * track.scale);
ctx.moveTo((element.x+0.75) * track.scale, (element.y+0.25) * track.scale);
@ -223,25 +183,24 @@ function trackDrawElement(ctx, element, mode) {
if (element.type == RAILWAY_SENSOR) {
ctx.beginPath();
ctx.arc((element.x+0.5) * track.scale, (element.y+0.5) * track.scale, track.scale*0.25, 0, 2 * Math.PI);
if (element.name == "") ctx.fillStyle = cssVar('--track-color-error');
else if (sensor_IsActive(element.name)) ctx.fillStyle = cssVar('--sensor-active');
else ctx.fillStyle = cssVar('--sensor-inactive');
if (element.name == "") ctx.fillStyle = 'DeepPink';
else if (sensor_IsActive(element.name)) ctx.fillStyle = 'LightGreen';
else ctx.fillStyle = 'DimGray';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = cssVar('--track-border');
ctx.strokeStyle = "#000000";
ctx.stroke();
}
//
// draw ref. name
if (element.name && sideBtnCmdGet() == "cmd-track-detail") {
if (element.type != RAILWAY_TEXT && element.type != RAILWAY_CONNECTOR
&& element.type != RAILWAY_BLOCK) {
if (element.name && sideBtnModeGet() == "mode-turn") {
if (element.type != RAILWAY_TEXT && element.type != RAILWAY_CONNECTOR) {
ctx.font = "10px Arial";
ctx.textAlign = "left";
if (element.name != "") {
ctx.fillStyle = cssVar('--track-element-fgborder');
ctx.fillStyle = "black";
ctx.fillText(element.name, (element.x) * track.scale -1, 6+(element.y+0.5) * track.scale );
ctx.fillText(element.name, (element.x) * track.scale +1, 6+(element.y+0.5) * track.scale );
ctx.fillText(element.name, (element.x) * track.scale , 6+(element.y+0.5) * track.scale -1);
@ -251,7 +210,7 @@ function trackDrawElement(ctx, element, mode) {
ctx.fillText(element.name, (element.x) * track.scale +1, 6+(element.y+0.5) * track.scale -1);
ctx.fillText(element.name, (element.x) * track.scale +1, 6+(element.y+0.5) * track.scale +1);
ctx.fillText(element.name, (element.x) * track.scale -1, 6+(element.y+0.5) * track.scale +1);
ctx.fillStyle = cssVar('--track-element-fg');
ctx.fillStyle = "white";
ctx.fillText(element.name, (element.x) * track.scale , 6+(element.y+0.5) * track.scale );
}
}
@ -261,160 +220,70 @@ function trackDrawElement(ctx, element, mode) {
};
function trackDrawBlock(ctx, blockelm) {
if (blockelm.dir == 1 || blockelm.dir == 2) { // 1 .. | 2.. -
let x1, y1, x2, y2, a, b;
let text, color;
let block;
// select color depending on referecedBy
for (var i = 0; i < blocks.length; i++) {
if (blockelm.name == blocks[i].name) {
block = blocks[i];
break;
}
}
// Fill Box
x1 = 0 * track.scale + 2;
y1 = (-1) * track.scale + 2;
x2 = ( 1) * track.scale - 2;
y2 = ( 2) * track.scale - 2;
if (blockelm.dir == 2) {
a = y1; y1 = x1; x1 = a;
b = y2; y2 = x2; x2 = b;
}
x1 = x1 + (blockelm.x) * track.scale;
x2 = x2 + (blockelm.x) * track.scale;
y1 = y1 + (blockelm.y) * track.scale;
y2 = y2 + (blockelm.y) * track.scale;
// console.log ("Flags:" + Number(blockelm.flags) + " Res:" + (Number(blockelm.flags) & BLOCK_F_OFF));
if (block && Number(block.flags) & BLOCK_F_OFF) ctx.fillStyle = cssVar('--block-bg-closed');
else if (blockelm.lockedby && blockelm.lockedby != "") ctx.fillStyle = cssVar('--block-bg-locked');
else ctx.fillStyle = cssVar('--block-bg');
ctx.fillRect (x1, y1, (x2-x1), (y2-y1));
ctx.beginPath();
ctx.lineWidth = 2;
ctx.setLineDash([0,0]);
ctx.strokeStyle = cssVar('--track-border');
ctx.moveTo(x1+0.5, y1+0.5);
ctx.lineTo(x2+0.5, y1+0.5);
ctx.lineTo(x2+0.5, y2+0.5);
ctx.lineTo(x1+0.5, y2+0.5);
ctx.lineTo(x1+0.5, y1+0.5);
ctx.stroke();
if (blockelm.dir == 2) {
x1 = (0.5 + blockelm.x) * track.scale;
y1 = (0.5 + blockelm.y) * track.scale + 5;
ctx.font = "10px Arial";
ctx.textAlign = "center";
if (block && Number(block.flags) & BLOCK_F_OFF) ctx.fillStyle = cssVar('--block-fg-closed');
else if (blockelm.lockedby && blockelm.lockedby != "") ctx.fillStyle = cssVar('--block-fg-locked');
else ctx.fillStyle = cssVar('--block-fg');
let li;
text = blockelm.name;
for (li = 0; li < locomotives.length; li++)
if (locomotives[li].name == blockelm.lockedby) {
if (locomotives[li].blockassign.substring(2,2+blockelm.lockedby.length) == blockelm.name) {
if (locomotives[li].blockassign.substring(0,1) == "-") text = "<= "+blockelm.lockedby;
else text = blockelm.lockedby + " =>";
}
else {
text = blockelm.lockedby;
}
}
ctx.fillText(text, x1, y1);
} else {
x1 = (0.5 + blockelm.x) * track.scale + 5;
y1 = (0.5 + blockelm.y) * track.scale;
ctx.save();
ctx.translate(x1, y1);
ctx.rotate(-Math.PI/2);
ctx.font = "10px Arial";
ctx.textAlign = "center";
if (block && Number(block.flags) & BLOCK_F_OFF) ctx.fillStyle = cssVar('--block-fg-closed');
else if (blockelm.lockedby && blockelm.lockedby != "") ctx.fillStyle = cssVar('--block-fg-locked');
else ctx.fillStyle = cssVar('--block-fg');
let li;
text = blockelm.name;
for (li = 0; li < locomotives.length; li++)
if (locomotives[li].name == blockelm.lockedby) {
if (locomotives[li].blockassign.substring(2,2+blockelm.lockedby.length) == blockelm.name) {
if (locomotives[li].blockassign.substring(0,1) == "-") text = blockelm.lockedby + " =>";
else text = "<= " + blockelm.lockedby;
}
else text = blockelm.lockedby;
}
ctx.fillText(text, 0, 0);
ctx.restore();
}
}
else {
ctx.beginPath();
ctx.lineWidth = 1;
ctx.setLineDash([0,0]);
ctx.strokeStyle = cssVar('--track-color-error');
ctx.moveTo((blockelm.x+0.25) * track.scale, (blockelm.y+0.25) * track.scale);
ctx.lineTo((blockelm.x+0.75) * track.scale, (blockelm.y+0.75) * track.scale);
ctx.moveTo((blockelm.x+0.75) * track.scale, (blockelm.y+0.25) * track.scale);
ctx.lineTo((blockelm.x+0.25) * track.scale, (blockelm.y+0.75) * track.scale);
ctx.stroke();
}
};
function trackDraw() {
var ctx = track.dbuf.getContext("2d");
var elm = {};
var tmpblocks = new Array();
// console.log ("trackDraw pos: " + trackMouse.pos.x + "," + trackMouse.pos.y +
// " down: " + trackMouse.down.x + "," + trackMouse.down.y);
// debug ("trackDraw pos: " + trackMouse.pos.x + "," + trackMouse.pos.y +
// " down: " + trackMouse.down.x + "," + trackMouse.down.y);
//
// clear screen
ctx.fillStyle = cssVar('--track-bg');
ctx.fillStyle = "#808080";
ctx.fillRect(0, 0, track.size.x * track.scale, track.size.y * track.scale);
//
// draw elements
for (var i = 0; i < track.elements.length; i++) if (track.elements[i]) {
if (track.elements[i].type == RAILWAY_BLOCK) {
tmpblocks.push (track.elements[i]);
}
//
for (var i = 0; i < track.elements.length; i++) {
trackDrawElement(ctx, track.elements[i], 0);
}
//
// draw block
for (var i = 0; i < tmpblocks.length; i++) {
trackDrawBlock(ctx, tmpblocks[i]);
// draw down position
if (trackMouse.down.x >= 0) {
var p1 = {};
var p2 = {};
if (trackMouse.pos.x < trackMouse.down.x) {
p1.x = trackMouse.pos.x;
p2.x = trackMouse.down.x;
}
else {
p1.x = trackMouse.down.x;
p2.x = trackMouse.pos.x;
}
if (trackMouse.pos.y < trackMouse.down.y) {
p1.y = trackMouse.pos.y;
p2.y = trackMouse.down.y;
}
else {
p1.y = trackMouse.down.y;
p2.y = trackMouse.pos.y;
}
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([2,2]);
ctx.strokeStyle = "#0000FF";
ctx.beginPath();
ctx.moveTo(0.5+(p1.x + 0) * track.scale, 0.5+(p1.y+0) * track.scale);
ctx.lineTo(0.5+(p2.x + 1) * track.scale, 0.5+(p1.y+0) * track.scale);
ctx.lineTo(0.5+(p2.x + 1) * track.scale, 0.5+(p2.y+1) * track.scale);
ctx.lineTo(0.5+(p1.x + 0) * track.scale, 0.5+(p2.y+1) * track.scale);
ctx.lineTo(0.5+(p1.x + 0) * track.scale, 0.5+(p1.y+0) * track.scale);
ctx.stroke();
}
tmpblocks.length = 0;
//
// draw mouse cursor
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([2,2]);
ctx.strokeStyle = cssVar('--track-element-fgborder');
ctx.strokeStyle = "#000000";
ctx.beginPath();
ctx.moveTo(0.5+(trackMouse.pos.x + 0) * track.scale, 0.5+(trackMouse.pos.y+0) * track.scale);
ctx.lineTo(0.5+(trackMouse.pos.x + 1) * track.scale, 0.5+(trackMouse.pos.y+0) * track.scale);
@ -425,98 +294,27 @@ function trackDraw() {
//
// draw mouseselection
var mode = sideBtnCmdGet();
var mode = sideBtnModeGet();
if (mode == "cmd-track-rail" || mode == "cmd-track-delete") {
if (trackMouse.down.x >= 0 && trackMouse.down.y >= 0) {
var selected = new Array();
selected.length = 0;
selected = trackGetElementList(trackMouse.down, trackMouse.pos, trackMouse.direction);
for (i = 0; i < selected.length; i++) {
trackDrawElement(ctx, selected[i], 1);
}
selected.length = 0;
var infoline = document.getElementById("infoline");
if (infoline) infoline.innerHTML = trackMouse.direction;
if ((mode == "mode-rail" || mode == "mode-delete") &&
trackMouse.down.x >= 0 && trackMouse.down.y >= 0) {
var selected = new Array();
selected.length = 0;
selected = trackGetElementList(trackMouse.down, trackMouse.pos, trackMouse.direction);
for (i = 0; i < selected.length; i++) {
trackDrawElement(ctx, selected[i], 1);
}
selected.length = 0;
var infoline = document.getElementById("infoline");
if (infoline) infoline.innerHTML = trackMouse.direction;
}
else if (mode == "cmd-track-move") {
if (trackMouse.step == 0) {
// draw rectangle for selection
let x1, x2, y1, y2;
// sort position down < pos
if (trackMouse.pos.x > trackMouse.down.x) {
x1 = trackMouse.down.x;
x2 = trackMouse.pos.x;
}
else {
x2 = trackMouse.down.x;
x1 = trackMouse.pos.x;
}
if (trackMouse.pos.y > trackMouse.down.y) {
y1 = trackMouse.down.y;
y2 = trackMouse.pos.y;
}
else {
y2 = trackMouse.down.y;
y1 = trackMouse.pos.y;
}
if (trackMouse.down.x >= 0) {
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([2,2]);
ctx.strokeStyle = cssVar('--track-element-fgborder');
ctx.beginPath();
ctx.moveTo(0.5+(x1 + 0) * track.scale, 0.5+(y1+0) * track.scale);
ctx.lineTo(0.5+(x2 + 1) * track.scale, 0.5+(y1+0) * track.scale);
ctx.lineTo(0.5+(x2 + 1) * track.scale, 0.5+(y2+1) * track.scale);
ctx.lineTo(0.5+(x1 + 0) * track.scale, 0.5+(y2+1) * track.scale);
ctx.lineTo(0.5+(x1 + 0) * track.scale, 0.5+(y1+0) * track.scale);
ctx.stroke();
}
}
else if (trackMouse.step == 1) {
let dx = trackMouse.pos.x - trackMouse.down.x;
let dy = trackMouse.pos.y - trackMouse.down.y;
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([2,2]);
ctx.strokeStyle = cssVar('--track-element-selectframe');
ctx.beginPath();
ctx.moveTo(0.5+(trackMouse.rect.x1 + 0) * track.scale, 0.5+(trackMouse.rect.y1+0) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x2 + 1) * track.scale, 0.5+(trackMouse.rect.y1+0) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x2 + 1) * track.scale, 0.5+(trackMouse.rect.y2+1) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x1 + 0) * track.scale, 0.5+(trackMouse.rect.y2+1) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x1 + 0) * track.scale, 0.5+(trackMouse.rect.y1+0) * track.scale);
ctx.stroke();
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([1,1]);
ctx.strokeStyle = cssVar('--track-element-selectframe');
ctx.beginPath();
ctx.moveTo(0.5+(trackMouse.rect.x1 + dx + 0) * track.scale, 0.5+(trackMouse.rect.y1 + dy + 0) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x2 + dx + 1) * track.scale, 0.5+(trackMouse.rect.y1 + dy + 0) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x2 + dx + 1) * track.scale, 0.5+(trackMouse.rect.y2 + dy + 1) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x1 + dx + 0) * track.scale, 0.5+(trackMouse.rect.y2 + dy + 1) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x1 + dx + 0) * track.scale, 0.5+(trackMouse.rect.y1 + dy + 0) * track.scale);
ctx.stroke();
}
}
else if (mode == "cmd-track-rail" || mode == "cmd-track-detail" || mode == "cmd-track-none" || mode == "cmd-none") {
}
else alert("track.js: unknown mode:" + mode);
//
// draw possible turnout
else if (mode == "mode-turn") {
var t = trackGetTurnout({x: trackMouse.pos.x, y: trackMouse.pos.y});
}
//
// flip screen - double buffering
@ -556,10 +354,10 @@ function trackMouseGetPos(event) {
function trackMousemove(event) {
var mode = sideBtnCmdGet();
var mode = sideBtnModeGet();
trackMouse.pos = trackMouseGetPos(event);
// console.log ("trackMousemove pos: " + trackMouse.pos.x + "," + trackMouse.pos.y +
// debug ("trackMousemove pos: " + trackMouse.pos.x + "," + trackMouse.pos.y +
// " subx: " + trackMouse.pos.subx + " suby:" + trackMouse.pos.suby);
trackDraw();
@ -567,17 +365,14 @@ function trackMousemove(event) {
function trackMousedown(event) {
var mode = sideBtnCmdGet();
var mode = sideBtnModeGet();
var tmp = trackMouseGetPos(event);
if (mode == "cmd-track-rail" || mode == "cmd-track-delete") {
if (mode == "mode-rail" || mode == "mode-delete") {
trackMouse.down = trackMouseGetPos(event);
}
else if (mode == "cmd-track-move") {
if (trackMouse.step == 0) trackMouse.down = trackMouseGetPos(event);
}
// console.log ("trackMousedown pos: " + tmp.x + "," + tmp.y + " subx: " + tmp.subx + " suby:" + tmp.suby);
// debug ("trackMousedown pos: " + tmp.x + "," + tmp.y + " subx: " + tmp.subx + " suby:" + tmp.suby);
trackDraw();
};
@ -587,17 +382,14 @@ function trackMousedown(event) {
//
//
function trackMouseup(event) {
var mode = sideBtnCmdGet();
var mode = sideBtnModeGet();
var tmp = trackMouseGetPos(event);
console.log ("trackMouseup tmp: " + tmp.x + "," + tmp.y + " mode:" + mode);
console.log ("trackMouseup down: " + trackMouse.down.x + "," + trackMouse.down.y);
console.log ("trackMouseup pos: " + trackMouse.pos.x + "," + trackMouse.pos.y);
console.log ("trackMouseup step: " + trackMouse.step);
gContextmenuClose();
debug ("trackMouseup tmp: " + tmp.x + "," + tmp.y + " mode:" + mode);
debug ("trackMouseup down: " + trackMouse.down.x + "," + trackMouse.down.y);
debug ("trackMouseup pos: " + trackMouse.pos.x + "," + trackMouse.pos.y);
if (mode == "cmd-track-rail") {
if (mode == "mode-rail") {
var pos = {};
var selected = new Array();
@ -605,17 +397,13 @@ function trackMouseup(event) {
selected = trackGetElementList(trackMouse.down, trackMouse.pos, trackMouse.direction);
serverinout_addTrack(selected);
selected.length = 0;
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
else if (mode == "cmd-track-detail") {
else if (mode == "mode-turn") {
rwdetail_show(trackMouse.pos.x, trackMouse.pos.y);
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
else if (mode == "cmd-track-delete") {
else if (mode == "mode-delete") {
var pos = {};
var xs, ys, xe ,ye;
var selected = new Array();
@ -642,63 +430,23 @@ function trackMouseup(event) {
ye = trackMouse.down.y;
}
debug ("delete: xs: " + xs + " , " + ys + " xe: " + xe + " , " + ye);
for (x = xs; x <= xe; x++) for (y = ys; y <= ye; y++) {
selected.push({x: x, y: y, dir: 1, type: 0});
}
serverinout_delTrack(selected);
selected.length = 0;
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
else if (mode == "cmd-track-move") {
if (trackMouse.step == 0) {
let x1, x2, y1, y2;
// sort position down < pos
if (trackMouse.pos.x > trackMouse.down.x) {
trackMouse.rect.x1 = trackMouse.down.x;
trackMouse.rect.x2 = trackMouse.pos.x;
}
else {
trackMouse.rect.x2 = trackMouse.down.x;
trackMouse.rect.x1 = trackMouse.pos.x;
}
if (trackMouse.pos.y > trackMouse.down.y) {
trackMouse.rect.y1 = trackMouse.down.y;
trackMouse.rect.y2 = trackMouse.pos.y;
}
else {
trackMouse.rect.y2 = trackMouse.down.y;
trackMouse.rect.y1 = trackMouse.pos.y;
}
trackMouse.step = 1;
trackMouse.down = trackMouse.pos;
}
else if (trackMouse.step == 1) {
//
// move railways
let dx = trackMouse.pos.x - trackMouse.down.x;
let dy = trackMouse.pos.y - trackMouse.down.y;
trackMoveArea(trackMouse.rect, dx, dy);
trackMouse.step = 0;
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
else {
trackMouse.step = 0;
}
}
else {
console.log ("rw_Click was das?");
rw_Click(trackMouse.pos.x, trackMouse.pos.y);
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
trackMouse.down.x = -1;
trackMouse.down.y = -1;
trackMouse.step = 0;
trackDraw();
};
@ -707,10 +455,10 @@ function trackMouseup(event) {
// add/or delete element
// fill in element
function trackAddElement(elm) {
// console.log ("trackAddElement: pos:" + elm.x + "," + elm.y + " d: " + elm.dir + " name:" + elm.name + " type:" + elm.type);
//debug ("trackAddElement: pos:" + elm.x + "," + elm.y + " d: " + elm.dir + " name:" + elm.name + " type:" + elm.type);
if (track.size.x > 0 && track.size.y > 0) {
track.elements[elm.x + track.size.x * elm.y] = elm;
track.elements[elm.x + track.size.y * elm.y] = elm;
}
};
@ -720,7 +468,7 @@ function trackAddElement(elm) {
// init the track view screen
// bind callback functions
function trackCreate(sizex, sizey) {
console.log ("trackCreate " + sizex + " , " + sizey);
debug ("trackCreate " + sizex + " , " + sizey);
var canvas = document.createElement("canvas");
track.size.x = sizex;
@ -746,7 +494,7 @@ function trackCreate(sizex, sizey) {
//
// get the size fo track from server, setup all data
function trackSetup(tracksetup) {
console.log ("trackSetup");
debug ("trackSetup");
var client = document.getElementById("page_main");
var oldc = document.getElementById("TrackCanvas");
@ -838,7 +586,7 @@ function trackGetElementList(start, end) {
}
else {
// should not possible but somehow we ended up here
console.log ("trackGetElementList: ERROR elm 3 or 5 expected");
debug ("trackGetElementList: ERROR elm 3 or 5 expected");
break;
}
}
@ -861,7 +609,7 @@ function trackGetElementList(start, end) {
}
else {
// should not possible but somehow we ended up here
console.log ("trackGetElementList: ERROR elm 4 or 6 expected");
debug ("trackGetElementList: ERROR elm 4 or 6 expected");
break;
}
}
@ -897,7 +645,6 @@ function trackGetElementList(start, end) {
return list;
};
//
// returns the element at the givin point
function trackGetTurnout(mousepos) {
@ -913,40 +660,3 @@ function trackGetTurnout(mousepos) {
return elm;
};
//
// trackMoveArea: moves an area from one to another place, it will overwrite the objects on this place.
//
function trackMoveArea (rect, dx, dy) {
let elmMove = new Array();
let elmDel = new Array();
let elm;
let x, y, idx;
if (dx == 0 && dy == 0) return;
for (x = rect.x1; x <= rect.x2; x++) for (y = rect.y1; y <= rect.y2; y++) {
idx = x + y * track.size.x;
elm = track.elements[idx];
if (!elm) {
elm = { x: x + dx,
y: y + dy,
type: RAILWAY_T_NOTHING,
dir: 0,
altdir: 0,
name: "" };
}
else {
elm.x = elm.x + dx;
elm.y = elm.y + dy;
}
elmMove.push (track.elements[idx]);
elm = {x: x, y: y};
elmDel.push (elm);
}
serverinout_delTrack(elmDel);
serverinout_addTrack(elmMove);
};

@ -1,123 +0,0 @@
# .SILENT:
DEPENDFILE=.depend
VERSION=0.1
#
# default configuration
# after chaning run make config
# default ports: 21105, 21106 and 3472?
PREFIX=/usr/local
DATAPREFIX=/var/lib
RUNPID=/var/run/z21Emulation.pid
ETCPREFIX=/etc
# DEFAULT_Z21PORT=21105
DEFAULT_Z21PORT=21104
#
#
#
ifndef CXX
CXX=g++
endif
#CXX=/data/CreateImages/RaspberryPi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-g++
CXXFLAGS= -ggdb -fPIC -Wall -pg
LDFLAGS= -lm -lc -pg
#
#
#
all: dep z21emu
# install: $(OBJSLAVES) collect-master collectd
# cp -rf collectd $(PREFIX)/bin
# cp -rf collect-master $(PREFIX)/bin
# $(foreach i,$(OBJSLAVES), cp -rf $(i) $(PREFIX)/bin;)
#
# mkdir -p $(ETCPREFIX)/collect
# $(foreach i,$(shell ls *.conf.sample), cp -rvf $(i) $(ETCPREFIX)/collect/;)
# $(foreach i,$(shell ls *.map), cp -rvf $(i) $(ETCPREFIX)/collect/;)
# $(foreach i,$(shell ls *.conf), echo $(i);)
# mkdir -p $(DATAPREFIX)/collect
#
#
# installinitd: install
# cp -rf collectd.sh /etc/init.d
# ln -fs ../init.d/collectd.sh /etc/rc2.d/S20collectd.sh
# ln -fs ../init.d/collectd.sh /etc/rc0.d/K10collectd.sh
# ln -fs ../init.d/collectd.sh /etc/rc1.d/K10collectd.sh
# ln -fs ../init.d/collectd.sh /etc/rc6.d/K10collectd.sh
#
# uninstall:
# rm -rf $(PREFIX)/bin/collectd
# rm -rf $(PREFIX)/bin/collect-master
# rm -rf /etc/init.d/collectd.sh
# rm -rf /etc/rc2.d/S10collectd.sh
# rm -rf /etc/rc0.d/K10collectd.sh
# rm -rf /etc/rc1.d/K10collectd.sh
# rm -rf /etc/rc6.d/K10collectd.sh
#
# $(foreach i,$(OBJSLAVES), rm -rf $(PREFIX)/bin/$(i);)
# # rm -rf $(ETCPREFIX)/collect
#
z21emu: z21emu.o udp.o debug.o z21prot.o i2csensor.o
$(CXX) $^ -o $@ $(LDFLAGS)
config:
echo "#ifndef _CONFIG_H_" > config.h
echo "#define _CONFIG_H_" >> config.h
echo "" >> config.h
echo "#define VERSION \"$(VERSION)\"" >> config.h
echo "" >> config.h
echo "#define PREFIX \"$(PREFIX)\"" >> config.h
echo "#define RUNPID \"$(RUNPID)\"" >> config.h
echo "#define DATAPREFIX \"$(DATAPREFIX)\"" >> config.h
echo "#define ETCPREFIX \"$(ETCPREFIX)\"" >> config.h
echo "" >> config.h
echo "#define DEFAULT_Z21PORT $(DEFAULT_Z21PORT)" >> config.h
echo "" >> config.h
# ifeq ($(HAVE_SIMPLEHD),1)
# echo "#define HAVE_SIMPLEHD 1" >> config.h
# else
# echo "// #define HAVE_SIMPLEHD 1" >> config.h
# endif
echo "" >> config.h
echo "#endif" >> config.h
rebuild: clean all
dep:
$(CXX) -MM `ls *.cc` $(CXXFLAGS) > $(DEPENDFILE)
dist:
mkdir z21emu-$(VERSION)
cp -rf *.conf.sample z21emu-$(VERSION)/
cp -rf *.cc z21emu-$(VERSION)/
cp -rf *.h z21emu-$(VERSION)/
cp -rf *.sh z21emu-$(VERSION)/
cp -rf Makefile z21emu-$(VERSION)/
cp -rf INSTALL z21emu-$(VERSION)/
tar cvzf z21emu-$(VERSION).tgz z21emu-$(VERSION)
rm -rf z21emu-$(VERSION)
clean:
rm *.s -rf
rm *.o -rf
rm *.oo -rf
rm *~ -rf
rm -rf .depend
rm -rf *.so
rm -rf *.so.*
rm -rf z21emu
rm -rf gmon.out
rm -rf config.h
rm -rf Makefile.rules
cleanall: clean
source: cleanall
-include $(DEPENDFILE)

@ -1,41 +0,0 @@
# .SILENT:
# Atmega88
# CFLAGS= -Os -g -Wall -mmcu=atmega16 -DF_CPU=8000000UL
# LDFLAGS= -mmcu=atmega16
CPUTYPE1= atmega16
CPUTYPE2= m16
# Atmega32
CFLAGS= -Os -g -Wall -mmcu=$(CPUTYPE1) -DF_CPU=16000000UL
LDFLAGS= -mmcu=$(CPUTYPE1)
all: gleiserkennung-v3.bin
%.o: %.c
avr-gcc $(CFLAGS) -c -o $@ $^
rebuild: clean all
gleiserkennung-v3.elf: gleiserkennung-v3.o eprom.o
avr-gcc $^ -o $@ $(LDFLAGS)
%.bin: %.elf
avr-objcopy -j .text -j .data -O binary $^ $@
clean:
rm *.o -rf
rm *.bin -rf
rm *.elf -rf
rm *~ -rf
cleanall: clean
source: cleanall
upload-v3: gleiserkennung-v3.bin
avrdude -c avrispmkII -P usb -p $(CPUTYPE2) -v -V -U flash:w:gleiserkennung-v3.bin:r

@ -1,26 +0,0 @@
/*
* eprom.c
*
* Created on: 11.02.2018
* Author: steffen
*/
#include "eprom.h"
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address and data registers
EEDR = ucData;
EECR |= (1<<EEMWE); // Write logical one to EEMWE
EECR |= (1<<EEWE); // Start eeprom write by setting EEWE
}
unsigned char EEPROM_read(unsigned int uiAddress) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address register
EECR |= (1<<EERE); // Start eeprom read by writing EERE
return EEDR; // return eeprom data register
}

@ -1,18 +0,0 @@
/*
* eprom.h
*
* Created on: 11.02.2018
* Author: steffen
*/
#ifndef EPROM_H_
#define EPROM_H_
#include <avr/io.h>
#include <avr/interrupt.h>
void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
unsigned char EEPROM_read(unsigned int uiAddress);
#endif /* ATMEGA8_DETECT_EPROM_H_ */

@ -1,283 +0,0 @@
/************************************************************
* reads some dis and make them readable over i2c bus.
*
* Atmega 16
* +-------+
* S26 (XCK/T0) PB0 -|1 O 40|- PA0 (ADC0) S14
* S25 (T1) PB1 -|2 39|- PA1 (ADC1) S13
* S24 (INT2/AIN0) PB2 -|3 38|- PA2 (ADC2) S12
* S23 (OC0/AIN1) PB3 -|4 37|- PA3 (ADC3) S11
* S22 (SS) PB4 -|5 36|- PA4 (ADC4) S10
* (MOSI) PB5 -|6 35|- PA5 (ADC5) S9
* (MISO) PB6 -|7 34|- PA6 (ADC6) S8
* (SCK) PB7 -|8 33|- PA7 (ADC7)
* RESET -|9 32|- AREF
* VCC -|10 31|- GND
* GND -|11 30|- AVCC
* XTAL2 -|12 29|- PC7 (TOSC2) S7
* XTAL1 -|13 28|- PC6 (TOSC1) S6
* S21 (RXD) PD0 -|14 27|- PC5 (TDI) S5
* S20 (TXD) PD1 -|15 26|- PC4 (TDO) S4
* S19 (INT0) PD2 -|16 25|- PC3 (TMS) S3
* S18 (INT1) PD3 -|17 24|- PC2 (TCK) S2
* S17 (OC1B) PD4 -|18 23|- PC1 (DSA) I2C
* S16 (OC1A) PD5 -|19 22|- PC0 (SCL) I2C
* S15 (ICP1) PD6 -|20 21|- PD7 (OC2) S1
* +-------+ */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.h"
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
#define I2C_DEFAULT_ADDR 0x2F
#define VERSION 3
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
uint32_t cnt[32] = { 0 };
unsigned int i;
uint32_t inval = 0;
uint32_t temp = 0;
int offdelay;
//
// disable JTAG
MCUCSR |= (1<<JTD);
MCUCSR |= (1<<JTD);
// enable inputs
DDRA = 0;
PORTA = 0xFF;
DDRB = 0;
PORTB = 0xFF;
DDRC = 0;
PORTC = 0xFF;
DDRD = 0;
PORTD = 0xFF;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
for (i = 0; i < 32; i++) cnt[i] = 0;
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
// S1 - S14
i = 0; if (!(PIND & (1 << 7))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 7))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 0))) cnt[i] = offdelay;
// S15 - S26
i++; if (!(PIND & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 0))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 0))) cnt[i] = offdelay;
// all values
for (i = 0; i < 16; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
for (i = 0; i < 16; i++) {
if (cnt[16+i] == 0) temp &= ~(1 << (i));
else {
cnt[16+i]--;
temp |= (1 << (i));
}
}
i2c_regs[0] = (unsigned char) (inval & 0x000000FF);
i2c_regs[1] = (unsigned char) ((inval & 0x0000FF00) >> 8);
i2c_regs[2] = (unsigned char) (temp & 0x000000FF);
i2c_regs[3] = (unsigned char) ((temp & 0x0000FF00) >> 8);
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};

@ -1,41 +0,0 @@
# .SILENT:
# Atmega88
# CFLAGS= -Os -g -Wall -mmcu=atmega16 -DF_CPU=8000000UL
# LDFLAGS= -mmcu=atmega16
CPUTYPE1= atmega32
CPUTYPE2= m32
# Atmega32
CFLAGS= -Os -g -Wall -mmcu=$(CPUTYPE1) -DF_CPU=16000000UL
LDFLAGS= -mmcu=$(CPUTYPE1)
all: gleiserkennung-v4.bin
%.o: %.c
avr-gcc $(CFLAGS) -c -o $@ $^
rebuild: clean all
gleiserkennung-v4.elf: gleiserkennung-v4.o eprom.o
avr-gcc $^ -o $@ $(LDFLAGS)
%.bin: %.elf
avr-objcopy -j .text -j .data -O binary $^ $@
clean:
rm *.o -rf
rm *.bin -rf
rm *.elf -rf
rm *~ -rf
cleanall: clean
source: cleanall
upload-v4: gleiserkennung-v4.bin
avrdude -c avrispmkII -P usb -p $(CPUTYPE2) -v -V -U flash:w:gleiserkennung-v4.bin:r

@ -1,26 +0,0 @@
/*
* eprom.c
*
* Created on: 11.02.2018
* Author: steffen
*/
#include "eprom.h"
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address and data registers
EEDR = ucData;
EECR |= (1<<EEMWE); // Write logical one to EEMWE
EECR |= (1<<EEWE); // Start eeprom write by setting EEWE
}
unsigned char EEPROM_read(unsigned int uiAddress) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address register
EECR |= (1<<EERE); // Start eeprom read by writing EERE
return EEDR; // return eeprom data register
}

@ -1,18 +0,0 @@
/*
* eprom.h
*
* Created on: 11.02.2018
* Author: steffen
*/
#ifndef EPROM_H_
#define EPROM_H_
#include <avr/io.h>
#include <avr/interrupt.h>
void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
unsigned char EEPROM_read(unsigned int uiAddress);
#endif /* ATMEGA8_DETECT_EPROM_H_ */

@ -1,281 +0,0 @@
/******************************************************************
* reads some digital inputs and make them readable over i2c bus.
*
* Atmega 32
* +-------+
* S17 (XCK/T0) PB0 -|1 O 40|- PA0 (ADC0) S9
* S18 (T1) PB1 -|2 39|- PA1 (ADC1) S10
* S19 (INT2/AIN0) PB2 -|3 38|- PA2 (ADC2) S11
* S20 (OC0/AIN1) PB3 -|4 37|- PA3 (ADC3) S12
* S21 (SS) PB4 -|5 36|- PA4 (ADC4) S13
* S22 (MOSI) PB5 -|6 35|- PA5 (ADC5) S14
* S23 (MISO) PB6 -|7 34|- PA6 (ADC6) S15
* S24 (SCK) PB7 -|8 33|- PA7 (ADC7) S16
* RESET -|9 32|- AREF
* VCC -|10 31|- GND
* GND -|11 30|- AVCC
* XTAL2 -|12 29|- PC7 (TOSC2)
* XTAL1 -|13 28|- PC6 (TOSC1)
* S1 (RXD) PD0 -|14 27|- PC5 (TDI)
* S2 (TXD) PD1 -|15 26|- PC4 (TDO)
* S3 (INT0) PD2 -|16 25|- PC3 (TMS)
* S4 (INT1) PD3 -|17 24|- PC2 (TCK)
* S5 (OC1B) PD4 -|18 23|- PC1 (DSA) I2C
* S6 (OC1A) PD5 -|19 22|- PC0 (SCL) I2C
* S7 (ICP1) PD6 -|20 21|- PD7 (OC2) S8
* +-------+ */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.h"
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
#define I2C_DEFAULT_ADDR 0x2F
#define VERSION 4
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
uint32_t cnt[32] = { 0 };
unsigned int i;
uint32_t inval = 0;
uint32_t temp = 0;
int offdelay;
//
// disable JTAG
MCUCSR |= (1<<JTD);
MCUCSR |= (1<<JTD);
// enable inputs
DDRA = 0;
PORTA = 0xFF;
DDRB = 0;
PORTB = 0xFF;
DDRC = 0;
PORTC = 0xFF;
DDRD = 0;
PORTD = 0xFF;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
for (i = 0; i < 32; i++) cnt[i] = 0;
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
// S1 - S8
i = 0; if (!(PINB & (1 << 0))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 7))) cnt[i] = offdelay;
// S9 - S16
i++; if (!(PINA & (1 << 0))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 7))) cnt[i] = offdelay;
// S17 - S24
i++; if (!(PIND & (1 << 0))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 7))) cnt[i] = offdelay;
// all values
for (i = 0; i < 16; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
for (i = 0; i < 16; i++) {
if (cnt[16+i] == 0) temp &= ~(1 << (i));
else {
cnt[16+i]--;
temp |= (1 << (i));
}
}
i2c_regs[0] = (unsigned char) (inval & 0x000000FF);
i2c_regs[1] = (unsigned char) ((inval & 0x0000FF00) >> 8);
i2c_regs[2] = (unsigned char) (temp & 0x000000FF);
i2c_regs[3] = (unsigned char) ((temp & 0x0000FF00) >> 8);
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};

@ -1,47 +0,0 @@
# .SILENT:
# Atmega88
# CFLAGS= -Os -g -Wall -mmcu=atmega16 -DF_CPU=8000000UL
# LDFLAGS= -mmcu=atmega16
CPUTYPE1= atmega8
CPUTYPE2= m8
# Atmega32
CFLAGS= -Os -g -Wall -mmcu=$(CPUTYPE1) -DF_CPU=16000000UL
LDFLAGS= -mmcu=$(CPUTYPE1)
all: gleiserkennung-v1.bin gleiserkennung-v2.bin
%.o: %.c
avr-gcc $(CFLAGS) -c -o $@ $^
rebuild: clean all
gleiserkennung-v2.elf: gleiserkennung-v2.o eprom.o
avr-gcc $^ -o $@ $(LDFLAGS)
gleiserkennung-v1.elf: gleiserkennung-v1.o eprom.o
avr-gcc $^ -o $@ $(LDFLAGS)
%.bin: %.elf
avr-objcopy -j .text -j .data -O binary $^ $@
clean:
rm *.o -rf
rm *.bin -rf
rm *.elf -rf
rm *~ -rf
cleanall: clean
source: cleanall
upload-v1: gleiserkennung-v1.bin
avrdude -c avrispmkII -P usb -p $(CPUTYPE2) -v -V -U flash:w:gleiserkennung-v1.bin:r
upload-v2: gleiserkennung-v2.bin
avrdude -c avrispmkII -P usb -p $(CPUTYPE2) -v -V -U flash:w:gleiserkennung-v2.bin:r

@ -1,26 +0,0 @@
/*
* eprom.c
*
* Created on: 11.02.2018
* Author: steffen
*/
#include "eprom.h"
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address and data registers
EEDR = ucData;
EECR |= (1<<EEMWE); // Write logical one to EEMWE
EECR |= (1<<EEWE); // Start eeprom write by setting EEWE
}
unsigned char EEPROM_read(unsigned int uiAddress) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address register
EECR |= (1<<EERE); // Start eeprom read by writing EERE
return EEDR; // return eeprom data register
}

@ -1,18 +0,0 @@
/*
* eprom.h
*
* Created on: 11.02.2018
* Author: steffen
*/
#ifndef EPROM_H_
#define EPROM_H_
#include <avr/io.h>
#include <avr/interrupt.h>
void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
unsigned char EEPROM_read(unsigned int uiAddress);
#endif /* ATMEGA8_DETECT_EPROM_H_ */

@ -1,247 +0,0 @@
/************************************************************
* reads some digital in and make them readable over i2c bus.
* register 0 -
*
* +-------+
* (RESET) PC6 -|1 O 28|- PC5 (ADC5/SCL)
* S3 (RXD) PD0 -|2 27|- PC4 (ADC4/SDA)
* S2 (TXD) PD1 -|3 26|- PC3 (ADC3)
* S1 (INT0) PD2 -|4 25|- PC2 (ADC2) S12
* S10 (INT1) PD3 -|5 24|- PC1 (ADC1) S16
* S7 (XCK/T0)PD4 -|6 23|- PC0 (ADC0) S15
* VCC -|7 22|- GND
* GND -|8 21|- AREF
* S8 (XTAL2/TOSC2) PB6 -|9 20|- AVCC
* S9 (XTAL2/TOSC2) PB7 -|10 19|- PB5 (SCK)
* S4 (T1) PD5 -|11 18|- PB4 (MISO)
* S5 (AIN0) PD6 -|12 17|- PB3 (MOSI(OC2)
* S6 (AIN1) PD7 -|13 16|- PB2 (SS/OC1B) S14
* S11 (ICP1) PB0 -|14 15|- PB1 (OC1A) S13
* +-------+
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.h"
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
#define I2C_DEFAULT_ADDR 0x4F
#define VERSION 1
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_DOOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
long int cnt[16] = { 0 };
unsigned int i;
unsigned short int inval = 0;
unsigned short int temp = 0;
int offdelay;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_system[I2C_SREG_DOOFFDELAY] = EEPROM_read(I2C_SREG_DOOFFDELAY);
if (i2c_system[I2C_SREG_DOOFFDELAY] == 0) {
i2c_system[I2C_SREG_DOOFFDELAY] = 0xFF;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
i = 0;
if (PIND & (1 << 2)) cnt[0] = offdelay;
if (PIND & (1 << 1)) cnt[1] = offdelay;
if (PIND & (1 << 0)) cnt[2] = offdelay;
if (PIND & (1 << 5)) cnt[3] = offdelay;
if (PIND & (1 << 6)) cnt[4] = offdelay;
if (PIND & (1 << 7)) cnt[5] = offdelay;
if (PIND & (1 << 4)) cnt[6] = offdelay;
if (PINB & (1 << 6)) cnt[7] = offdelay;
if (PINB & (1 << 7)) cnt[8] = offdelay;
if (PIND & (1 << 3)) cnt[9] = offdelay;
if (PINB & (1 << 0)) cnt[10] = offdelay;
if (PINC & (1 << 2)) cnt[11] = offdelay;
if (PINB & (1 << 1)) cnt[12] = offdelay;
if (PINB & (1 << 2)) cnt[13] = offdelay;
if (PINC & (1 << 0)) cnt[14] = offdelay;
if (PINC & (1 << 1)) cnt[15] = offdelay;
// all values
for (i = 0; i < 16; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
i2c_regs[0] = (unsigned char) (inval & 0x00FF);
i2c_regs[1] = (unsigned char) ((inval & 0xFF00) >> 8);
temp++;
i2c_regs[2] = (unsigned char) (temp & 0x00FF);
i2c_regs[3] = (unsigned char) ((temp & 0xFF00) >> 8);
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};

@ -1,250 +0,0 @@
/************************************************************
* reads some dis and make them readable over i2c bus.
* out of 8 registers only the register 1 is needed
*
* +-------+
* (RESET) PC6 -|1 O 28|- PC5 (ADC5/SCL)
* Sensor 1 (RXD) PD0 -|2 27|- PC4 (ADC4/SDA)
* Sensor 2 (TXD) PD1 -|3 26|- PC3 (ADC3) Relais 1
* Sensor 3 (INT0) PD2 -|4 25|- PC2 (ADC2) Relais 2
* Sensor 4 (INT1) PD3 -|5 24|- PC1 (ADC1) Relais 3
* Sensor 5 (XCK/T0) PD4 -|6 23|- PC0 (ADC0) Relais 4
* VCC -|7 22|- GND
* GND -|8 21|- AREF
* Sen6(XTAL2/TOSC2) PB6 -|9 20|- AVCC
* Sen7(XTAL2/TOSC2) PB7 -|10 19|- PB5 (SCK)
* Sensor 8 (T1) PD5 -|11 18|- PB4 (MISO)
* (AIN0) PD6 -|12 17|- PB3 (MOSI(OC2)
* Relais 7 (AIN1) PD7 -|13 16|- PB2 (SS/OC1B) Relais 5
* Relais 8 (ICP1) PB0 -|14 15|- PB1 (OC1A) Relais 6
* +-------+
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.h"
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
#define VERSION 2
#define I2C_DEFAULT_ADDR 0x4F
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_DOOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
long int cnt[8] = { 0 };
unsigned int i;
char inval = 0;
int offdelay;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_system[I2C_SREG_DOOFFDELAY] = EEPROM_read(I2C_SREG_DOOFFDELAY);
if (i2c_system[I2C_SREG_DOOFFDELAY] == 0) {
i2c_system[I2C_SREG_DOOFFDELAY] = 0xFF;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
DDRB |= 1 | (1<<1) | (1<<2);
DDRC |= 1 | (1<<1) | (1<<2) | (1<<3);
DDRD |= (1<<7);
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
if (PIND & 0x01) cnt[0] = offdelay;
if (PIND & 0x02) cnt[1] = offdelay;
if (PIND & 0x04) cnt[2] = offdelay;
if (PIND & 0x08) cnt[3] = offdelay;
if (PIND & 0x10) cnt[4] = offdelay;
if (PINB & 0x40) cnt[5] = offdelay;
if (PINB & 0x80) cnt[6] = offdelay;
if (PIND & 0x20) cnt[7] = offdelay;
for (i = 0; i < 8; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
i2c_regs[0] = inval;
//
// digital out registers..
if (i2c_regs[1] & 0x01) PORTC |= (1 << 3);
else PORTC &= ~(1 << 3);
if (i2c_regs[1] & 0x02) PORTC |= (1 << 2);
else PORTC &= ~(1 << 2);
if (i2c_regs[1] & 0x04) PORTC |= (1 << 1);
else PORTC &= ~(1 << 1);
if (i2c_regs[1] & 0x08) PORTC |= 1;
else PORTC &= ~1;
if (i2c_regs[1] & 0x10) PORTB |= (1 << 2);
else PORTB &= ~(1 << 2);
if (i2c_regs[1] & 0x20) PORTB |= (1 << 1);
else PORTB &= ~(1 << 1);
if (i2c_regs[1] & 0x40) PORTD |= (1 << 7);
else PORTD &= ~(1 << 7);
if (i2c_regs[1] & 0x80) PORTB |= 1;
else PORTB &= ~1;
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};

@ -1,153 +0,0 @@
/************************************************************
* reads some dis and make them readable over i2c bus.
* out of 8 registers only the register 1 is needed
*
* +-------+
* (RESET) PC6 -|1 O 28|- PC5 (ADC5/SCL)
* (RXD) PD0 -|2 27|- PC4 (ADC4/SDA)
* (TXD) PD1 -|3 26|- PC3 (ADC3)
* (INT0) PD2 -|4 25|- PC2 (ADC2)
* (INT1) PD3 -|5 24|- PC1 (ADC1) Sensor 4
* (XCK/T0) PD4 -|6 23|- PC0 (ADC0) Sensor 3
* VCC -|7 22|- GND
* GND -|8 21|- AREF
* (XTAL2/TOSC2) PB6 -|9 20|- AVCC
* (XTAL2/TOSC2) PB7 -|10 19|- PB5 (SCK)
* Sensor 8 (T1) PD5 -|11 18|- PB4 (MISO)
* Sensor 7 (AIN0) PD6 -|12 17|- PB3 (MOSI(OC2)
* Sensor 6 (AIN1) PD7 -|13 16|- PB2 (SS/OC1B) Sensor 2
* Sensor 5 (ICP1) PB0 -|14 15|- PB1 (OC1A) Sensor 1
* +-------+
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
volatile int i2c_reg;
volatile uint8_t i2c_inregs[I2C_NUM_REGS];
volatile uint8_t i2c_outregs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
char i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_inregs[i] = i;
i2c_outregs[i] = i | 0x80;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS)
i2c_reg = data;
else
i2c_reg = 0; // FIXME: wrong address so start at register 0
TWCR_ACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_inregs[i2c_reg] = data;
i2c_reg++;
}
TWCR_ACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_outregs[i2c_reg];
// TWDR = 0xF3;
i2c_reg++;
}
else {
TWDR = 0; //Kein Daten mehr im Buffer
}
TWCR_ACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
#define OFFDELAY 0x2000;
int main( void ) {
long int cnt[8] = { 0 };
unsigned int i;
char inval = 0;
long int t;
// i2c benutzt PORTC bit5+C4
i2c_slave_init (0x30);
while( 1 ) {
if (PINB & 0x02) cnt[0] = OFFDELAY;
if (PINB & 0x04) cnt[1] = OFFDELAY;
if (PINC & 0x02) cnt[2] = OFFDELAY;
if (PINC & 0x01) cnt[3] = OFFDELAY;
if (PINB & 0x01) cnt[4] = OFFDELAY;
if (PIND & 0x80) cnt[5] = OFFDELAY;
if (PIND & 0x40) cnt[6] = OFFDELAY;
if (PIND & 0x20) cnt[7] = OFFDELAY;
for (i = 0; i < 8; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
i2c_outregs[1] = inval;
}
return 0;
};

@ -1,45 +0,0 @@
/*
* debug.cc
*
* Created on: 15.12.2017
* Author: steffen
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
char *int2hex (int val, char *buf, int len) {
char tmp[] = "0123456789ABCDEF";
int i;
unsigned int v;
if (buf == NULL) return NULL;
memset (buf, '0', len-1);
buf[len-1] = 0;
for (v = val, i = 0; i < len-1; i++) {
buf[len-2-i] = tmp[v % 16];
v = v >> 4;
}
return buf;
}
void debug_mem (char *c, int len) {
int i;
int v;
char _hexpos[32];
char _hexval[32];
for (i = 0; i < len; i++) {
if (i > 0 && (i % 16) == 0) printf ("\n");
if ((i % 16) == 0)
printf (" 0x%s ", int2hex(i, _hexpos, 5));
if ((i % 8) == 0) printf (" ");
v = (unsigned char) c[i];
printf ("%s ", int2hex(v, _hexval, 3));
}
printf ("\n");
};

@ -1,16 +0,0 @@
/*
* debug.h
*
* Created on: 15.12.2017
* Author: steffen
*/
#ifndef DEBUG_H_
#define DEBUG_H_
void debug_mem (char *c, int len);
char *int2hex (int val, char *buf, int len);
#endif /* DEBUG_H_ */

@ -1,105 +0,0 @@
/*
* i2csensor.cc
*
* Created on: 18.12.2017
* Author: steffen
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include "i2csensor.h"
#define LEN_FILENAME 255
#define LEN_BUFFER 32
I2C::I2C () {
i2cdev = 1;
};
I2C::~I2C () {
};
bool I2C::ReadByte(int addr, int reg, uint8_t *readval) {
int file;
char filename[LEN_FILENAME];
unsigned char buffer[LEN_BUFFER];
if (readval == NULL) return false;
// i2c device
snprintf(filename, 255, "/dev/i2c-%d", i2cdev);
file = open(filename, O_RDWR);
if (file < 0) {
return false;
}
// setup slave addresse
if (ioctl(file, I2C_SLAVE, addr) < 0) {
close (file);
return false;
}
usleep (10000);
// write register
buffer[0] = reg;
if (write(file, buffer, 1) != 1) {
close (file);
return false;
}
// read value
if (read(file, buffer, 1) != 1) {
close (file);
return false;
}
*readval = buffer[0];
close (file);
return true;
};
bool I2C::SendByte(int addr, int reg, uint8_t data) {
int file;
char filename[LEN_FILENAME];
unsigned char buffer[LEN_BUFFER];
// i2c device
snprintf(filename, 255, "/dev/i2c-%d", i2cdev);
file = open(filename, O_RDWR);
if (file < 0) {
return false;
}
// setup slave addresse
if (ioctl(file, I2C_SLAVE, addr) < 0) {
close (file);
return false;
}
usleep (10000);
// write register and value
buffer[0] = reg;
buffer[1] = data;
if (write(file, buffer, 2) != 2) {
close (file);
return false;
}
close (file);
return true;
};

@ -1,31 +0,0 @@
/*
* i2csensor.h
*
* Created on: 18.12.2017
* Author: steffen
*/
#ifndef I2CSENSOR_H_
#define I2CSENSOR_H_
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string>
using namespace std;
class I2C {
private:
int i2cdev;
public:
I2C ();
~I2C ();
bool ReadByte(int addr, int reg, uint8_t *readval);
bool SendByte(int addr, int reg, uint8_t data);
};
#endif /* I2CSENSOR_H_ */

@ -1,183 +0,0 @@
/*
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /* close() */
#include <string.h> /* memset() */
#include "udp.h"
char dnsip[NET_HOSTLEN];
int dns_filladdr (string host, string port, int ai_family, struct sockaddr_in *sAddr) {
struct addrinfo hints, *res;
int err;
/* we have to complete the sAddr struct */
bzero (&hints, sizeof (struct addrinfo));
hints.ai_family = ai_family;
hints.ai_socktype = SOCK_DGRAM;
if ((err = getaddrinfo (host.c_str(), port.c_str(), &hints, &res)) < 0) {
fprintf (stdout, "dns_filladdr (getaddrinfo):%s\n", gai_strerror (err));
return -1;
}
memcpy (sAddr, res->ai_addr, res->ai_addrlen);
freeaddrinfo (res);
return 1;
};
UDPConnection::UDPConnection() {
sock = -1;
port = "";
writecnt = 0;
readcnt = 0;
};
UDPConnection::~UDPConnection() {
Close();
}
void UDPConnection::Close () {
if (sock > -1) close (sock);
sock = -1;
}
int UDPConnection::Listen(int port) {
struct sockaddr_in servAddr;
/* socket creation */
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("%s: socket error: %s \n",__FUNCTION__, strerror(errno));
return 0;
}
/* bind local server port */
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port);
if (bind (sock, (struct sockaddr *) &servAddr,sizeof(servAddr)) < 0) {
printf("%s: bind error: %s \n",__FUNCTION__, strerror(errno));
return 0;
}
return 1;
}
int UDPConnection::Listen(string port) {
return Listen (atoi(port.c_str()));
}
long int UDPConnection::ReadTimeout(string *source, char *buffer, long int len, int timeout) {
int i;
i = isData(timeout);
if (i > 0) {
return Read (source, buffer, len);
}
else
return i;
}
long int UDPConnection::Read(string *source, char *buffer, long int len) {
int n;
socklen_t addrlen;
sockaddr_in srcAddr;
if (!isListen()) return -1;
memset(buffer, 0x0, len);
addrlen = sizeof(srcAddr);
n = recvfrom(sock, buffer, len, 0, (sockaddr *) &srcAddr, &addrlen);
if(n<0) {
printf("%s: recvfrom error:%s\n",__FUNCTION__, strerror(errno));
return -1;
}
/* print received message */
char addr[NET_HOSTLEN];
snprintf (addr, NET_HOSTLEN, "%s:%d", inet_ntoa(srcAddr.sin_addr), ntohs(srcAddr.sin_port));
(*source) = (char*)addr;
return n;
}
long int UDPConnection::Send(string destaddr, char *buffer, long int len) {
int s;
int addrlen = sizeof (struct sockaddr_in);
sockaddr_in dstAddr;
string host;
string port;
if (!isListen()) {
/* socket creation */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("%s: socket error: %s \n",__FUNCTION__, strerror(errno));
return -1;
}
}
else s = sock;
int pos = destaddr.rfind(':', destaddr.length());
if (pos == -1) {
port = "NET_PORT";
host = destaddr;
}
else {
port = destaddr.substr (pos+1, destaddr.length() - pos);
host = destaddr.substr (0, pos);
}
dns_filladdr (host, port, PF_INET, &dstAddr);
if (sendto (s, buffer, len, 0, (sockaddr *) &dstAddr, addrlen) == -1) {
printf("%s: sendto error: %s \n",__FUNCTION__, strerror(errno));
return -1;
}
if (!isListen()) close (s);
return 1;
}
int UDPConnection::isListen() {
return (sock != -1);
}
int UDPConnection::isData(int timeout) {
fd_set sockset;
struct timeval tval;
if (sock <= 0) {
printf ("isData:socket error\n");
return -1;
}
FD_ZERO (&sockset);
FD_SET (sock, &sockset);
tval.tv_sec = timeout / 1000;
tval.tv_usec = (timeout % 1000);
if (select (sock + 1, &sockset, NULL, NULL, &tval) >= 0) {
if (FD_ISSET (sock, &sockset)) {
return 1;
}
}
return 0;
}

@ -1,55 +0,0 @@
#ifndef _SP_UDP_H_
#define _SP_UDP_H_
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include "config.h"
using namespace std;
#define NET_HOSTLEN 128
#define NET_PORTLEN 6
#define NET_BUFFERSIZE 1024
class UDPConnection {
private:
string port;
int sock;
size_t readcnt;
size_t writecnt;
public:
UDPConnection();
~UDPConnection();
int Listen(int port);
int Listen(string port);
long int ReadTimeout(string *srcaddr, char *buffer, long int len, int timeout);
long int Read(string *srcaddr, char *buffer, long int len);
long int Send(string destaddr, char *buffer, long int len);
void Close();
int isListen();
int isData(int timeout); // timeout in ms;
int getSocket() { return sock; };
void setSocket(int s);
};
#endif

@ -1,296 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "config.h"
#include "udp.h"
#include "debug.h"
#include "z21prot.h"
#include "z21emu.h"
#include "i2csensor.h"
using namespace std;
struct s_rbussensor rbus[RBUS_MAXSENSORBYTES] = { 0 };
struct s_xlanturnout xlturn[XLAN_TURNOUT_MAX] = { 0 };
void i2cloop(I2C *i2c);
void i2cscan(I2C *i2c);
void i2ccfgprint();
int i2ccfgload(const char *fname);
int debug = 0;
void help();
int main (int argc, char **argv) {
// time_t t1, t2;
string cfgfile = DEFAULT_CONFIG;
Z21Server z21server;
I2C i2c;
int i;
int numofclients = 0;
for (i = 1; i < argc; i++) {
if (strcmp (argv[i], "-help") == 0) {
help();
exit (0);
}
if (strcmp (argv[i], "-scan") == 0) {
i2cscan(&i2c);
i2ccfgprint();
exit (0);
}
if (strcmp (argv[i], "-debug") == 0) {
debug = 1;
}
if (strcmp (argv[i], "-config") == 0) {
i++;
cfgfile = argv[i];
printf ("using configfile: %s\n", cfgfile.c_str());
}
}
if (i2ccfgload(cfgfile.c_str()) == 0) {
i2cscan(&i2c);
}
z21server.Start();
while ( 1 ) {
//
// for detection of changed values
for (i = 0; i < RBUS_MAXSENSORBYTES; i++)
rbus[i].last = rbus[i].status;
/* t2 = time (NULL);
if (t2-t1 > 1) {
rbus_status[2]++;
rbus_status[15]--;
t1 = t2;
}
*/
if (numofclients > 0) i2cloop (&i2c);
numofclients = z21server.Loop();
usleep(25000);
};
return 0;
};
void i2cloop (I2C *i2c) {
int index; // sensorbox number --> sbox + 0x30 = i2c address
//
// digital in
for (index = 0; index < RBUS_MAXSENSORBYTES; index++) {
if (rbus[index].i2c_addr != 0) {
if (!i2c->ReadByte(rbus[index].i2c_addr, rbus[index].i2c_reg, &rbus[index].status)) {
if (debug) printf ("i2cloop: Read ADDR:%02x REG:%02x Value:%2x Error\n", rbus[index].i2c_addr, rbus[index].i2c_reg, rbus[index].status);
rbus[index].status = 0xFF; // error
}
else if (debug) {
printf ("i2cloop: Read ADDR:%02x REG:%02x Value:%2x\n", rbus[index].i2c_addr, rbus[index].i2c_reg, rbus[index].status);
}
}
}
//
// digital out
for (index = 0; index < XLAN_TURNOUTBYTES; index++) {
if (xlturn[index].last != xlturn[index].output) {
// ignore if addr is not set
if (xlturn[index].i2c_addr == 0) xlturn[index].last = xlturn[index].output;
// send data
else if (i2c->SendByte(xlturn[index].i2c_addr, xlturn[index].i2c_reg, xlturn[index].output)) {
xlturn[index].last = xlturn[index].output;
}
}
}
}
//
// scan all i2c devices read version and create configuration
void i2cscan(I2C *i2c) {
int dicnt;
int docnt;
int addr;
unsigned char ver;
for (dicnt = 0, docnt = 0, addr = 0x20; addr < 0x7f; addr++) {
if (i2c->ReadByte(addr, 0x20, &ver)) {
if (ver == 1) {
if (dicnt < RBUS_MAXSENSORBYTES) {
rbus[dicnt].i2c_addr = addr;
rbus[dicnt].i2c_reg = 0x0;
dicnt++;
}
if (dicnt < RBUS_MAXSENSORBYTES) {
rbus[dicnt].i2c_addr = addr;
rbus[dicnt].i2c_reg = 0x1;
dicnt++;
}
}
else if (ver == 2) {
if (dicnt < RBUS_MAXSENSORBYTES) {
rbus[dicnt].i2c_addr = addr;
rbus[dicnt].i2c_reg = 0x0;
dicnt++;
}
if (docnt < RBUS_MAXSENSORBYTES) {
xlturn[docnt].i2c_addr = addr;
xlturn[docnt].i2c_reg = 0x1;
docnt++;
}
}
else if (ver == 3 || ver == 4) {
if (dicnt < RBUS_MAXSENSORBYTES) {
rbus[dicnt].i2c_addr = addr;
rbus[dicnt].i2c_reg = 0x0;
dicnt++;
}
if (dicnt < RBUS_MAXSENSORBYTES) {
rbus[dicnt].i2c_addr = addr;
rbus[dicnt].i2c_reg = 0x1;
dicnt++;
}
if (dicnt < RBUS_MAXSENSORBYTES) {
rbus[dicnt].i2c_addr = addr;
rbus[dicnt].i2c_reg = 0x2;
dicnt++;
}
if (dicnt < RBUS_MAXSENSORBYTES) {
rbus[dicnt].i2c_addr = addr;
rbus[dicnt].i2c_reg = 0x3;
dicnt++;
}
}
}
}
};
void i2ccfgprint() {
int i;
printf ("# autoscan configuration\n");
printf ("#\n");
printf ("# digital input configuration\n");
printf ("#\n");
printf ("# di NUM addr ADDR reg REG\n");
for (i = 0; i < RBUS_MAXSENSORBYTES; i++) if (rbus[i].i2c_addr != 0)
printf ("di %d addr %x reg %x\n", i, rbus[i].i2c_addr, rbus[i].i2c_reg);
printf ("#\n");
printf ("# digital output configuration\n");
printf ("#\n");
printf ("# do NUM addr ADDR reg REG\n");
for (i = 0; i < XLAN_TURNOUTBYTES; i++) if (xlturn[i].i2c_addr != 0)
printf ("do %d addr %x reg %x\n", i, xlturn[i].i2c_addr, xlturn[i].i2c_reg);
};
#define STR_TOK_NOSPACE(_pnt_) while (_pnt_[0] != 0 && (_pnt_[0] == ' ' || _pnt_[0] == '\t')) _pnt_++
#define STR_TOK_NEXT(_pnt_) while (_pnt_[0] != 0 && _pnt_[0] != ' ' && _pnt_[0] != '\t') _pnt_++
int i2ccfgload(const char *fname) {
FILE *f;
char buf[1024];
char *pos;
int index = -1;
int type;
int addr;
int reg;
printf ("loading file: %s\n", fname);
f = fopen (fname, (char*)"r");
if (f == NULL) {
printf ("error:%s\n", strerror(errno));
return 0;
}
while (fgets (buf, sizeof (buf), f) != NULL) {
pos = buf;
if (pos[0] == '#') continue;
type = I2CREGTYPE_UNDEF;
addr = 0;
reg = 0;
index = -1;
while (pos != NULL && pos[0] != 0) {
STR_TOK_NOSPACE(pos);
if (strncmp ("di", pos, strlen ("di")) == 0) {
STR_TOK_NEXT(pos);
sscanf (pos, "%d", &index);
type = I2CREGTYPE_DI;
printf (" di %d", index);
}
if (strncmp ("do", pos, strlen ("do")) == 0) {
STR_TOK_NEXT(pos);
sscanf (pos, "%d", &index);
type = I2CREGTYPE_DO;
printf (" do %d", index);
}
if (strncmp ("addr", pos, strlen ("addr")) == 0) {
STR_TOK_NEXT(pos);
sscanf (pos, "%x", &addr);
printf (" addr %x", addr);
}
if (strncmp ("reg", pos, strlen ("reg")) == 0) {
STR_TOK_NEXT(pos);
sscanf (pos, "%x", &reg);
printf (" reg %x", reg);
}
else STR_TOK_NEXT(pos);
}
if (type == I2CREGTYPE_DI && index >= 0 && index < RBUS_MAXSENSORBYTES) {
rbus[index].i2c_addr = addr;
rbus[index].i2c_reg = reg;
printf ("--> DI (%d) OK\n", index);
}
else if (type == I2CREGTYPE_DO && index >= 0 && index < XLAN_TURNOUTBYTES) {
xlturn[index].i2c_addr = addr;
xlturn[index].i2c_reg = reg;
printf ("--> DO (%d) OK\n", index);
}
else {
printf (" error\n");
}
}
fclose (f);
return 0;
};
#undef STR_TOK_NEXT
void help () {
printf ("z21emu:\n");
printf ("=======\n");
printf ("\n");
printf ("parameters: without any parameters the config will be read from file.\n");
printf (" if no file is found, autoscan is used first.\n");
printf (" -scan scanning i2c bus and print out a sample device config\n");
printf (" -debug enabling debugging\n");
printf (" -config FILE finename used for configuration (default %s/\n", DEFAULT_CONFIG);
printf ("\n");
}
void xlan_turnout (int addr, bool enable) {
int addrbyte = (addr-1)/8;
int bit = (addr-1)%8;
if (addr == 0) return;
if (addrbyte < 0 || addrbyte >= XLAN_TURNOUTBYTES) return;
if (enable) xlturn[addrbyte].output |= (1 << bit);
else xlturn[addrbyte].output &= ~(1 << bit);
}

@ -1,22 +0,0 @@
# autoscan configuration
# sensor NUM addr ADDR reg REG
sbox 0 addr 30 reg 0
sbox 1 addr 31 reg 0
sbox 2 addr 31 reg 1
sbox 3 addr 0 reg 0
sbox 4 addr 0 reg 0
sbox 5 addr 0 reg 0
sbox 6 addr 0 reg 0
sbox 7 addr 0 reg 0
sbox 8 addr 0 reg 0
sbox 9 addr 0 reg 0
sbox 10 addr 0 reg 0
sbox 11 addr 0 reg 0
sbox 12 addr 0 reg 0
sbox 13 addr 0 reg 0
sbox 14 addr 0 reg 0
sbox 15 addr 0 reg 0
sbox 16 addr 0 reg 0
sbox 17 addr 0 reg 0
sbox 18 addr 0 reg 0
sbox 19 addr 0 reg 0

@ -1,52 +0,0 @@
/*
* z21emu.h
*
* Created on: 16.12.2017
* Author: steffen
*/
#ifndef Z21EMU_H_
#define Z21EMU_H_
#include "config.h"
#define DEFAULT_CONFIG ETCPREFIX"/z21emu.conf"
#define RBUS_BYTESPERGROUP 10
#define RBUS_GROUPS 2
#define RBUS_MAXSENSORBYTES (RBUS_GROUPS*RBUS_BYTESPERGROUP)
#define XLAN_TURNOUT_MAX 1024
#define XLAN_TURNOUTBYTES (XLAN_TURNOUT_MAX / 8)
enum {
I2CREGTYPE_UNDEF,
I2CREGTYPE_DI,
I2CREGTYPE_DO
};
struct s_rbussensor {
unsigned char status; // current value
unsigned char last; // last value
unsigned char i2c_addr; // i2c address
unsigned char i2c_reg; // i2c register
};
extern struct s_rbussensor rbus[RBUS_MAXSENSORBYTES];
struct s_xlanturnout {
unsigned char i2c_addr; // i2c address
unsigned char i2c_reg; // i2c register
unsigned char output; // current value
unsigned char last; // last value
};
extern struct s_xlanturnout xlturn[XLAN_TURNOUT_MAX];
extern int debug;
void xlan_turnout (int addr, bool enable);
#endif /* Z21EMU_H_ */

@ -1,36 +0,0 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: z21emu
# Required-Start:
# Required-Stop:
# Should-Start:
# Default-Start:
# Default-Stop:
# Short-Description: z21 wrapper to support i2c sensors
# Description: z21 is a control device for model trains. this software implements a wrapper onto the z21 protocoll so you can connect some i2c devices to the rocrail or any other model train controlling software supporting z21.
### END INIT INFO
PATH=/sbin:/bin:/usr/local/bin:/usr/bin:/usr/sbin
case "$1" in
start)
/usr/local/bin/z21emu >&2 > /dev/null &
;;
restart|reload|force-reload)
echo "not pupported yet" >&2
exit 3
;;
stop)
killall z21emu
;;
status)
ps xa -H | grep z21emu
exit $?
;;
*)
echo "Usage: z21emu.sh [start|stop|status]" >&2
exit 3
;;
esac
:

@ -1,268 +0,0 @@
/*
* z21prot.cc
*
* Created on: 15.12.2017
* Author: steffen
*/
#include "config.h"
#include "z21prot.h"
#include "z21emu.h"
#include "debug.h"
Z21Client::Z21Client() {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
};
Z21Client::~Z21Client() {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
};
bool Z21Client::LoopData (UDPConnection *udp, char *buffer, size_t len) {
short unsigned int pktlen = le16toh(bufgetint16(buffer, 0));
short int pktheader = le16toh(bufgetint16(buffer, 2));
int i, k;
// LAN_GET_SERIAL_NUMBER
if (pktlen == 4 && pktheader == 0x10) {
bufsetint16 (outbuf, 0, htole16(8));
bufsetint16 (outbuf, 2, htole16(0x10));
bufsetint32 (outbuf, 4, htole32(55555953));
udp->Send(source, outbuf, 8);
}
// LAN_LOGOFF
else if (pktlen == 4 && pktheader == 0x0030) {
return false;
}
// LAN_X_ Commandos
else if (pktheader == 0x0040) {
if (pktlen > len) {
printf ("ERROR: got broken udp paket? pktlen(%d) > len(%ld)\n", pktlen, len);
} else {
Z21_lan_x_data xdata;
int pos = 4;
int chksum;
char db;
while (pos < pktlen) {
xdata.xheader = buffer[pos++];
for (i = 0; i < Z21_X_LEN && (unsigned int) i+pos < len; i++)
xdata.db[i] = buffer[pos+i];
// LAN_X_GET_VERSION
if (xdata.xheader == 0x21 &&
xdata.db[0] == 0x21 && xdata.db[1] == 0x00) {
printf ("LAN_X_GET_VERSION\n");
pos += 2;
bufsetint16 (outbuf, 0, htole16(9));
bufsetint16 (outbuf, 2, htole16(0x40));
k = 4;
bufsetint8 (outbuf, k++, db=0x63); // XHeader
chksum = db;
bufsetint8 (outbuf, k++, db=0x21); // DB0
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, db=0x30); // DB1
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, db=0x12); // DB2
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, chksum); // XOR-Byte
// debug_mem(outbuf, k);
udp->Send(source, outbuf, k);
}
// LAN_X_GET_FIRMWARE_VERSION
else if (xdata.xheader == 0xF1 &&
xdata.db[0] == 0x0A && xdata.db[1] == 0xFB) {
printf ("LAN_X_GET_FIRMWARE_VERSION\n");
pos += 3;
bufsetint16 (outbuf, 0, htole16(9)); // LEN
bufsetint16 (outbuf, 2, htole16(0x40)); // X_CMD
k = 4;
bufsetint8 (outbuf, k++, db=0xF3); // XHeader
chksum = db;
bufsetint8 (outbuf, k++, db=0x0A); // DB0
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, db=0x01); // DB1
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, db=0x20); // DB2
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, chksum); // XOR-Byte
// debug_mem(outbuf, k);
udp->Send(source, outbuf, k);
}
// LAN_X_SET_TURNOUT
else if (xdata.xheader == 0x53) {
int addr = (xdata.db[0] << 8) + xdata.db[1];
int cmd = xdata.db[2];
int cmd_q = cmd & 0x20;
int cmd_a = cmd & 0x08;
int cmd_p = cmd & 0x01;
pos += 4;
printf ("LAN_X_SETTURNOUT addr: %d cmd: %x (q:%d a:%d p:%d)\n", addr, cmd, cmd_q, cmd_a, cmd_p);
xlan_turnout (addr, (cmd_a != 0));
}
else {
printf ("LAN_X command not understood: %x\n", xdata.xheader);
}
}
}
}
// LAN_RMBUS_GETDATA --> send LAN_RMBUS_DATACHANGED
else if (pktheader == 0x0081 && pktlen == 5) {
unsigned char rmbus_grpidx = bufgetint8(buffer, 4);
printf ("LAN_RMBUS_GETDATA\n");
Send_LAN_RMBUS_DATACHANGED(udp, rmbus_grpidx);
}
else {
printf ("unknown command: ");
// debug_mem (buffer, len);
}
return true;
}
void Z21Client::Send_LAN_RMBUS_DATACHANGED (UDPConnection *udp, unsigned char grpidx) {
int k, i;
printf ("Send LAN_RMBUS_DATACHANGED\n");
if (grpidx >= RBUS_GROUPS) {
printf (" giving group (%d) is not supported.\n", grpidx);
return;
}
bufsetint16 (outbuf, 0, htole16(15)); // LEN
bufsetint16 (outbuf, 2, htole16(0x80)); // X_CMD
k = 4;
bufsetint8 (outbuf, k++, grpidx); // Gruppenindex
for (i = 0; i < RBUS_BYTESPERGROUP; i++)
bufsetint8 (outbuf, k++, rbus[grpidx*RBUS_BYTESPERGROUP + i].status);
udp->Send(source, outbuf, k);
}
/************************************************************************/
Z21Server::Z21Server () {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
};
Z21Server::~Z21Server () {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
};
void Z21Server::Start() {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
udp.Listen(DEFAULT_Z21PORT);
};
int Z21Server::Loop() {
string source;
size_t len;
int newclient = 1;
list<Z21Client*>::iterator iter;
int i, grp;
if (udp.isListen()) {
//
// read new data from UDP
len = udp.ReadTimeout(&source, buffer, NET_BUFFERSIZE, 25); // timeout 25ms
if (len > 0) {
//
// check known connection
newclient = 1;
iter = clients.begin();
while (iter != clients.end()) {
if ((*iter)->isSource(source)) {
newclient = 0;
if (!((*iter)->LoopData(&udp, buffer, len))) {
printf ("remove client: '%s' count:%ld\n", source.c_str(), clients.size());
iter = clients.erase(iter);
}
break;
}
iter++;
}
//
// new connection
if (newclient && iter == clients.end()) {
Z21Client *client;
client = new Z21Client();
client->setSource(source);
if (client->LoopData(&udp, buffer, len)) {
clients.push_back(client);
printf ("add client: '%s' count:%ld\n", source.c_str(), clients.size());
}
}
}
//
// broadcast changed values
for (grp = 0; grp < RBUS_GROUPS; grp++) {
for (i = 0; i < RBUS_BYTESPERGROUP; i++)
if (rbus[grp*RBUS_BYTESPERGROUP+i].status != rbus[grp*RBUS_BYTESPERGROUP+i].last) break;
if (i != RBUS_BYTESPERGROUP) {
//
// send broadcast to all clients
for (iter = clients.begin(); iter != clients.end(); iter++)
(*iter)->Send_LAN_RMBUS_DATACHANGED(&udp, grp);
}
}
}
return clients.size();
};
/************************************************************************/
uint8_t bufgetint8 (char *buf, int pos) {
int8_t i;
memcpy (&i, buf+pos, 1);
return i;
};
uint16_t bufgetint16 (char *buf, int pos) {
int16_t i;
memcpy (&i, buf+pos, 2);
return i;
};
uint32_t bufgetint32 (char *buf, int pos) {
int32_t i;
memcpy (&i, buf+pos, 4);
return i;
};
void bufsetint8 (char *buf, int pos, uint8_t i) {
memcpy (buf+pos, &i, 1);
};
void bufsetint16 (char *buf, int pos, uint16_t i) {
memcpy (buf+pos, &i, 2);
};
void bufsetint32 (char *buf, int pos, uint32_t i) {
memcpy (buf+pos, &i, 4);
};

@ -1,58 +0,0 @@
/*
* z21prot.h
*
* Created on: 15.12.2017
* Author: steffen
*/
#ifndef Z21PROT_H_
#define Z21PROT_H_
#include <list>
#include "udp.h"
#define Z21_X_LEN 16
struct {
unsigned char xheader;
unsigned char db[Z21_X_LEN];
} typedef Z21_lan_x_data;
//
// work around for memory alignment on some CPUs/PocketPCs
uint8_t bufgetint8 (char *buf, int pos);
uint16_t bufgetint16 (char *buf, int pos);
uint32_t bufgetint32 (char *buf, int pos);
void bufsetint8 (char *buf, int pos, uint8_t i);
void bufsetint16 (char *buf, int pos, uint16_t i);
void bufsetint32 (char *buf, int pos, uint32_t i);
class Z21Client {
private:
char outbuf[NET_BUFFERSIZE];
string source;
public:
Z21Client();
~Z21Client();
void setSource(string newsrc) { source = newsrc; };
string getSource() { return source; };
bool isSource(string srcaddr) { return (source.compare(srcaddr) == 0); };
bool LoopData (UDPConnection *udp, char *buffer, size_t len);
void Send_LAN_RMBUS_DATACHANGED (UDPConnection *udp, unsigned char grpidx);
};
class Z21Server{
private:
list<Z21Client*> clients;
UDPConnection udp;
char buffer[NET_BUFFERSIZE];
public:
Z21Server ();
~Z21Server ();
int Loop(); // returns number of connections
void Start();
};
#endif /* Z21PROT_H_ */
Loading…
Cancel
Save