diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7b66ef9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "knxPython/pybind11"] + path = knxPython/pybind11 + url = https://github.com/pybind/pybind11.git + branch = stable diff --git a/knxPython/CMakeLists.txt b/knxPython/CMakeLists.txt index fbcd90f..9849bd7 100644 --- a/knxPython/CMakeLists.txt +++ b/knxPython/CMakeLists.txt @@ -4,8 +4,8 @@ cmake_minimum_required(VERSION 2.7) project(knx) -set(LIBRARIES_FROM_REFERENCES "") -add_library(knx SHARED ../src/knx/address_table_object.cpp ../src/knx/apdu.cpp ../src/knx/application_layer.cpp ../src/knx/application_program_object.cpp ../src/knx/association_table_object.cpp ../src/knx/bau.cpp ../src/knx/bau07B0.cpp ../src/knx/bau57B0.cpp ../src/knx/bau_systemB.cpp ../src/knx/bits.cpp ../src/knx/cemi_frame.cpp ../src/knx/datapoint_types.cpp ../src/knx/data_link_layer.cpp ../src/knx/device_object.cpp ../src/knx/group_object.cpp ../src/knx/group_object_table_object.cpp ../src/knx/interface_object.cpp ../src/knx/ip_data_link_layer.cpp ../src/knx/ip_parameter_object.cpp ../src/knx/memory.cpp ../src/knx/network_layer.cpp ../src/knx/npdu.cpp ../src/knx/platform.cpp ../src/knx/table_object.cpp ../src/knx/tpdu.cpp ../src/knx/tpuart_data_link_layer.cpp ../src/knx/transport_layer.cpp ../src/linux_platform.cpp knxmodule.cpp) -target_link_libraries(knx python3.5m "${LIBRARIES_FROM_REFERENCES}") -include_directories(/usr/include/python3.5m ../src) -SET_TARGET_PROPERTIES(knx PROPERTIES PREFIX "") +add_subdirectory(pybind11) + +pybind11_add_module(knx ../src/knx/address_table_object.cpp ../src/knx/apdu.cpp ../src/knx/application_layer.cpp ../src/knx/application_program_object.cpp ../src/knx/association_table_object.cpp ../src/knx/bau.cpp ../src/knx/bau07B0.cpp ../src/knx/bau57B0.cpp ../src/knx/bau_systemB.cpp ../src/knx/bits.cpp ../src/knx/cemi_frame.cpp ../src/knx/datapoint_types.cpp ../src/knx/data_link_layer.cpp ../src/knx/device_object.cpp ../src/knx/group_object.cpp ../src/knx/group_object_table_object.cpp ../src/knx/interface_object.cpp ../src/knx/ip_data_link_layer.cpp ../src/knx/ip_parameter_object.cpp ../src/knx/memory.cpp ../src/knx/network_layer.cpp ../src/knx/npdu.cpp ../src/knx/platform.cpp ../src/knx/table_object.cpp ../src/knx/tpdu.cpp ../src/knx/tpuart_data_link_layer.cpp ../src/knx/transport_layer.cpp ../src/linux_platform.cpp knxmodule.cpp) + +include_directories(../src) \ No newline at end of file diff --git a/knxPython/gcc_Debug.h b/knxPython/gcc_Debug.h index 3018ca2..43caac5 100644 --- a/knxPython/gcc_Debug.h +++ b/knxPython/gcc_Debug.h @@ -862,7 +862,8 @@ #endif // --- Include directories begin --- // -///usr/include/python3.5m +///usr/include/python3.5dm +///usr/include/python3.5 ///usr/include/c++/6 ///usr/include/x86_64-linux-gnu/c++/6 ///usr/include/c++/6/backward @@ -871,6 +872,8 @@ ///usr/lib/gcc/x86_64-linux-gnu/6/include-fixed ///usr/include/x86_64-linux-gnu ///usr/include +//../src +//pybind11\include // --- Include directories end --- // diff --git a/knxPython/knxPython-Debug.vgdbsettings b/knxPython/knxPython-Debug.vgdbsettings index e701a62..dca4fc8 100644 --- a/knxPython/knxPython-Debug.vgdbsettings +++ b/knxPython/knxPython-Debug.vgdbsettings @@ -4,13 +4,41 @@ - RemoteUnix + Win10LXSS - localhost - LinuxSubsystem - Linux + Suzail + SSH + tkunze + + false + + Suzail + SSH + tkunze + + $(ProjectDir)\.. + /tmp/VisualGDB/$(ProjectDirUnixStyle)/.. + + *.cpp + *.h + *.hpp + *.c + *.cc + *.cxx + *.mak + Makefile + *.txt + *.cmake + *.py + + true + true + + false + true + false false false @@ -25,18 +53,17 @@ 0 - + knxPython DEBUG Debug - knx false BuildMachine BuiltinShortcut - ninja - + $(ToolchainMake) + $(ToolchainMakeArgs) $(BuildDir) @@ -49,10 +76,10 @@ $(ToolchainCMake) - true + false + $(BuildDir)/main.py false false - Ninja false @@ -93,14 +120,14 @@ false - false - false - false - false - false - false - false - false + true + true + true + true + true + true + true + true false false @@ -121,9 +148,10 @@ 0 - $(SourceDir)/main.py + $(TargetPath) 2000 + $(BuildDir)/Debug PYTHONPATH=%PYTHONPATH%:$(SourceDir)/$(ConfigurationName) python3 true @@ -131,10 +159,12 @@ false false + Local false false Auto + true false diff --git a/knxPython/knxPython.vcxproj b/knxPython/knxPython.vcxproj index 71c1fb4..e01fb5a 100644 --- a/knxPython/knxPython.vcxproj +++ b/knxPython/knxPython.vcxproj @@ -44,7 +44,7 @@ - $(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\python3.5m;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\c++\6;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\x86_64-linux-gnu\c++\6;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\c++\6\backward;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\lib\gcc\x86_64-linux-gnu\6\include;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\local\include;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\lib\gcc\x86_64-linux-gnu\6\include-fixed;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\x86_64-linux-gnu;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include;..\src;$(NMakeIncludeSearchPath) + $(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\python3.5dm;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\python3.5;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\c++\6;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\x86_64-linux-gnu\c++\6;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\c++\6\backward;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\lib\gcc\x86_64-linux-gnu\6\include;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\local\include;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\lib\gcc\x86_64-linux-gnu\6\include-fixed;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include\x86_64-linux-gnu;$(LOCALAPPDATA)\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs\usr\include;..\..\src;..\pybind11\include;$(NMakeIncludeSearchPath) $(ProjectDir)\gcc_Debug.h;$(VISUALGDB_DIR)\gcc_compat.h;$(NMakeForcedIncludes) "$(VISUALGDB_DIR)\VisualGDB.exe" /build "$(ProjectPath)" "/solution:$(SolutionPath)" "/config:$(Configuration)" "/platform:$(Platform)" "$(VISUALGDB_DIR)\VisualGDB.exe" /clean "$(ProjectPath)" "/solution:$(SolutionPath)" "/config:$(Configuration)" "/platform:$(Platform)" diff --git a/knxPython/knxmodule.cpp b/knxPython/knxmodule.cpp index d7e87c4..ebbbb8c 100644 --- a/knxPython/knxmodule.cpp +++ b/knxPython/knxmodule.cpp @@ -1,174 +1,158 @@ +#include +#include + +namespace py = pybind11; + #include #include -#include #include #include +#include +#include +#include #include "linux_platform.h" #include "knx/bau57B0.h" #include "knx/group_object_table_object.h" -LinuxPlatform platfrom; -Bau57B0 bau(platfrom); +LinuxPlatform platform; +Bau57B0 bau(platform); #if 1 // this code will go to python later -float currentValue = 0; -float maxValue = 0; -float minValue = RAND_MAX; -long lastsend = 0; +//float currentValue = 0; +//float maxValue = 0; +//float minValue = RAND_MAX; +//long lastsend = 0; +// +//GroupObject groupObjects[] +//{ +// GroupObject(2), +// GroupObject(2), +// GroupObject(2), +// GroupObject(1) +//} +//; +//#define CURR groupObjects[0] +//#define MAX groupObjects[1] +//#define MIN groupObjects[2] +//#define RESET groupObjects[3] +// +//void measureTemp() +//{ +// long now = platform.millis(); +// if ((now - lastsend) < 2000) +// return; +// +// lastsend = now; +// int r = rand(); +// currentValue = (r * 1.0) / (RAND_MAX * 1.0); +// currentValue *= 100 * 100; +// +// CURR.objectWrite(currentValue); +// +// if (currentValue > maxValue) +// { +// maxValue = currentValue; +// MAX.objectWrite(maxValue); +// } +// +// if (currentValue < minValue) +// { +// minValue = currentValue; +// MIN.objectWrite(minValue); +// } +//} -GroupObject groupObjects[] -{ - GroupObject(2), - GroupObject(2), - GroupObject(2), - GroupObject(1) -} -; -#define CURR groupObjects[0] -#define MAX groupObjects[1] -#define MIN groupObjects[2] -#define RESET groupObjects[3] +//void resetCallback(GroupObject& go) +//{ +// if (go.objectReadBool()) +// { +// maxValue = 0; +// minValue = 10000; +// } +//} -void measureTemp() -{ - long now = platfrom.millis(); - if ((now - lastsend) < 2000) - return; - - lastsend = now; - int r = rand(); - currentValue = (r * 1.0) / (RAND_MAX * 1.0); - currentValue *= 100 * 100; - - CURR.objectWrite(currentValue); - - if (currentValue > maxValue) - { - maxValue = currentValue; - MAX.objectWrite(maxValue); - } - - if (currentValue < minValue) - { - minValue = currentValue; - MIN.objectWrite(minValue); - } -} - -void resetCallback(GroupObject& go) -{ - if (go.objectReadBool()) - { - maxValue = 0; - minValue = 10000; - } -} - -void appLoop() -{ - if (!bau.configured()) - return; - - measureTemp(); -} +//void appLoop() +//{ +// if (!bau.configured()) +// return; +// +// measureTemp(); +//} void setup() { srand((unsigned int)time(NULL)); bau.readMemory(); - GroupObjectTableObject& got(bau.groupObjectTable()); - got.groupObjects(groupObjects, 4); +// GroupObjectTableObject& got(bau.groupObjectTable()); +// got.groupObjects(groupObjects, 4); DeviceObject& devObj(bau.deviceObject()); devObj.manufacturerId(0xfa); - RESET.updateHandler = resetCallback; +// RESET.updateHandler = resetCallback; - - if (bau.parameters().loadState() == LS_LOADED) - { - printf("Timeout: %d\n", bau.parameters().getWord(0)); - printf("Zykl. senden: %d\n", bau.parameters().getByte(2)); - printf("Min/Max senden: %d\n", bau.parameters().getByte(3)); - printf("Aenderung senden: %d\n", bau.parameters().getByte(4)); - printf("Abgleich %d\n", bau.parameters().getByte(5)); - } bau.enabled(true); } #endif -static void* loop(void* x) +bool threadEnabled = false; +static void loop() { while (1) { bau.loop(); - appLoop(); - platfrom.mdelay(100); + //appLoop(); + platform.mdelay(100); } - - pthread_exit(NULL); } -static pthread_t workerThread; +static std::thread workerThread; -static PyObject* Start(PyObject* self, PyObject* args) +bool started = false; +static void Start() { - if (!PyArg_ParseTuple(args, "")) - return NULL; - + if (started) + return; + setup(); - int res = pthread_create(&workerThread, NULL, loop, NULL); - if (res) - { - printf("error %d\n", res); - return NULL; - } - - Py_RETURN_NONE; + workerThread = std::thread(loop); + workerThread.detach(); } -static PyObject* ProgramMode(PyObject* self, PyObject* args) +static bool ProgramMode(bool value) { - if (PyArg_ParseTuple(args, "")) - { - //no arguments - return Py_BuildValue("i", bau.deviceObject().progMode()); - } - PyErr_Clear(); - int value = 0; - if (!PyArg_ParseTuple(args, "i", &value)) - return NULL; bau.deviceObject().progMode(value); - return Py_BuildValue("i", bau.deviceObject().progMode()); + return bau.deviceObject().progMode(); } -static PyMethodDef knxMethods[] = +static bool ProgramMode() { - {"Start", Start, METH_VARARGS, "Start knx handling thread." }, - {"ProgramMode", ProgramMode, METH_VARARGS, "Activate/deactivate programing mode." }, - { NULL, NULL, 0, NULL } /* End of list */ -}; - - -static struct PyModuleDef knxModule = { - PyModuleDef_HEAD_INIT, - "knx", - NULL, - 0, - knxMethods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC PyInit_knx(void) -{ - PyObject* m = PyModule_Create(&knxModule); - return m; + return bau.deviceObject().progMode(); } +static void RegisterGroupObjects(std::vector& gos) +{ + GroupObjectTableObject& got(bau.groupObjectTable()); + got.groupObjects(gos.data(), gos.size()); +} + +PYBIND11_MAKE_OPAQUE(std::vector); + +PYBIND11_MODULE(knx, m) { + m.doc() = "wrapper for knx device lib"; // optional module docstring + + py::bind_vector>(m, "GroupObjectList"); + + m.def("Start", &Start, "Start knx handling thread."); + m.def("ProgramMode", (bool (*)())&ProgramMode, "get programing mode active."); + m.def("ProgramMode", (bool(*)(bool))&ProgramMode, "Activate / deactivate programing mode."); + m.def("RegisterGroupObjects", &RegisterGroupObjects); + + py::class_(m, "GroupObject") + .def(py::init()) + .def("objectWrite", (void(GroupObject::*)(float))&GroupObject::objectWrite); +} \ No newline at end of file diff --git a/knxPython/main.py b/knxPython/main.py index 43141aa..39e104b 100644 --- a/knxPython/main.py +++ b/knxPython/main.py @@ -3,6 +3,14 @@ import time import sys print("start") +gos = knx.GroupObjectList() +gos.append(knx.GroupObject(2)) +gos.append(knx.GroupObject(2)) +gos.append(knx.GroupObject(2)) +gos.append(knx.GroupObject(1)) +curr = gos[0] +knx.RegisterGroupObjects(gos) +knx.Start() while True: time.sleep(1) cmd = sys.stdin.read(1) @@ -14,4 +22,10 @@ while True: elif cmd == 'p': currentMode = knx.ProgramMode(not knx.ProgramMode()) print("set programming mode to " + str(currentMode)) + elif cmd == 'w': + cmd = sys.stdin.read(4) + print(cmd) + value = float(cmd) + curr.objectWrite(value) + print("wrote " + str(value) + " to curr") print("end") \ No newline at end of file diff --git a/knxPython/pybind11 b/knxPython/pybind11 new file mode 160000 index 0000000..9a19306 --- /dev/null +++ b/knxPython/pybind11 @@ -0,0 +1 @@ +Subproject commit 9a19306fbf30642ca331d0ec88e7da54a96860f9 diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index ba6a6ec..a6df977 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -13,6 +13,17 @@ GroupObject::GroupObject(uint8_t size) updateHandler = 0; } +GroupObject::GroupObject(const GroupObject& other) +{ + _data = new uint8_t[other._dataLength]; + _commFlag = other._commFlag; + _table = other._table; + _dataLength = other._dataLength; + _asap = other._asap; + updateHandler = other.updateHandler; + memcpy(_data, other._data, _dataLength); +} + GroupObject::~GroupObject() { delete[] _data; diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 87248d2..9a17278 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -24,6 +24,7 @@ class GroupObject friend class GroupObjectTableObject; public: GroupObject(uint8_t size); + GroupObject(const GroupObject& other); virtual ~GroupObject(); // config flags from ETS bool responseUpdateEnable(); diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index a17d92e..2f2f693 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -25,6 +25,7 @@ #include "knx/group_object_table_object.h" #include "knx/application_program_object.h" #include "knx/ip_parameter_object.h" +#include "knx/bits.h" #define MAX_MEM 4096 @@ -129,8 +130,8 @@ void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port) fatalError(); } - /* Broadcast auf dieser Maschine zulassen */ - loop = 1; + /* loopback */ + loop = 0; if (setsockopt(_socketFd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { perror("setsockopt:IP_MULTICAST_LOOP"); @@ -184,6 +185,7 @@ bool LinuxPlatform::sendBytes(uint8_t* buffer, uint16_t len) return false; } } while (retVal == -1); +// printHex("<-", buffer, len); return true; } @@ -194,6 +196,9 @@ int LinuxPlatform::readBytes(uint8_t * buffer, uint16_t maxLen) sin_len = sizeof(sin); ssize_t len = recvfrom(_socketFd, buffer, maxLen, 0, (struct sockaddr *) &sin, &sin_len); +// if (len > 0) +// printHex("->", buffer, len); + return len; } diff --git a/src/linux_platform.h b/src/linux_platform.h index cf7c174..ff3ac6c 100644 --- a/src/linux_platform.h +++ b/src/linux_platform.h @@ -11,37 +11,37 @@ public: LinuxPlatform(); // ip stuff - uint32_t currentIpAddress(); - uint32_t currentSubnetMask(); - uint32_t currentDefaultGateway(); - void macAddress(uint8_t* addr); + uint32_t currentIpAddress() override; + uint32_t currentSubnetMask() override; + uint32_t currentDefaultGateway() override; + void macAddress(uint8_t* addr) override; // basic stuff - uint32_t millis(); - void mdelay(uint32_t millis); - void restart(); - void fatalError(); + uint32_t millis() override; + void mdelay(uint32_t millis) override; + void restart() override; + void fatalError() override; //multicast - void setupMultiCast(uint32_t addr, uint16_t port); - void closeMultiCast(); - bool sendBytes(uint8_t* buffer, uint16_t len); - int readBytes(uint8_t* buffer, uint16_t maxLen); + void setupMultiCast(uint32_t addr, uint16_t port) override; + void closeMultiCast() override; + bool sendBytes(uint8_t* buffer, uint16_t len) override; + int readBytes(uint8_t* buffer, uint16_t maxLen) override; //uart - void setupUart(); - void closeUart(); - int uartAvailable(); - size_t writeUart(const uint8_t data); - size_t writeUart(const uint8_t *buffer, size_t size); - int readUart(); - size_t readBytesUart(uint8_t *buffer, size_t length); + void setupUart() override; + void closeUart() override; + int uartAvailable() override; + size_t writeUart(const uint8_t data) override; + size_t writeUart(const uint8_t *buffer, size_t size) override; + int readUart() override; + size_t readBytesUart(uint8_t *buffer, size_t length) override; //memory - uint8_t* getEepromBuffer(uint16_t size); - void commitToEeprom(); - uint8_t* allocMemory(size_t size); - void freeMemory(uint8_t* ptr); + uint8_t* getEepromBuffer(uint16_t size) override; + void commitToEeprom() override; + uint8_t* allocMemory(size_t size) override; + void freeMemory(uint8_t* ptr) override; private: uint32_t _multicastAddr; uint16_t _port;