lpcmanager

merged revamp

2018-12-18, Edouard Tisserant
67800351d235
merged revamp
--- a/FirmwareUpdateDialog.py Wed Apr 11 13:06:58 2018 +0200
+++ b/FirmwareUpdateDialog.py Tue Dec 18 14:43:49 2018 +0100
@@ -29,91 +29,64 @@
This class is the dialog for firmware update parameters selection
"""
- def _init_ctrls(self, parent):
- wx.Dialog.__init__(self, parent=parent, size=wx.Size(600, 250), title=_('Firmware Update'))
+ def __init__(self, parent):
+ wx.Dialog.__init__(self, parent=parent, title=_('Firmware Update'))
# Widgets for the update image file selection
- self.StaticTextFirmwareUpdateImageFile = wx.StaticText(label=_('Update image file:'), parent=self)
self.TextCtrltFirmwareUpdateImageFile = wx.TextCtrl(self)
- self.TextCtrltFirmwareUpdateImageFile.SetMinSize((440, -1))
self.ButtonFirmwareUpdateImageFile = wx.Button(label=_('Add image file'), parent=self)
self.Bind(wx.EVT_BUTTON, self.OnButtonFirmwareUpdateImageFile, id=self.ButtonFirmwareUpdateImageFile.GetId())
- # Widgets for the update type
- self.StaticTextFirmwareUpdateType = wx.StaticText(label=_('Update type:'), parent=self)
- self.RadioButtonFirmwareUpdateTypeLinuxKernel = wx.RadioButton(self, -1,
- _('Linux kernel'), (10, 10), style=wx.RB_GROUP)
- self.RadioButtonFirmwareUpdateTypeLinuxDTB = wx.RadioButton(self, -1,
- _('Linux DTB'), (10, 30))
- self.RadioButtonFirmwareUpdateTypeRootFs = wx.RadioButton(self, -1,
- _('Root file system'), (10, 50))
# Widgets for the chunks size
- self.StaticTextFirmwareUpdateChunksSize = wx.StaticText(label=_('Chunks size in KiB:'), parent=self)
- self.SpinCtrlFirmwareUpdateChunksSize = wx.SpinCtrl(parent=self , size = (60, -1))
+ self.SpinCtrlFirmwareUpdateChunksSize = wx.SpinCtrl(parent=self)
self.SpinCtrlFirmwareUpdateChunksSize.SetRange(1, 1024)
self.SpinCtrlFirmwareUpdateChunksSize.SetValue(256)
- # Widgets for the reboot option
- self.CheckBoxFirmwareUpdateReboot = wx.CheckBox(label=_('Reboot after update'), parent=self)
-
# Widgets for validation
self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
# Sizers
- self.MainSizer = wx.FlexGridSizer(cols=1, rows=2)
- self.SizerFirmwareUpdateImageFile = wx.FlexGridSizer(cols=2, rows=2, hgap=10, vgap=10)
- self.SizerFirmwareUpdateTypeChunks = wx.FlexGridSizer(cols=2, rows=4, hgap=10, vgap=10)
-
- # Populate Main sizer
- self.MainSizer.Add(self.SizerFirmwareUpdateImageFile, flag=wx.EXPAND)
- self.MainSizer.Add(self.SizerFirmwareUpdateTypeChunks, flag=wx.EXPAND)
+ self.SizerFirmwareUpdateImageFile = wx.FlexGridSizer(cols=2, rows=1)
+ self.SizerFirmwareUpdateImageFile.AddGrowableCol(0)
+ self.SizerFirmwareUpdateImageFile.AddGrowableRow(0)
- # Make the main sizer rows and columns growable
- self.MainSizer.AddGrowableCol(0)
- self.MainSizer.AddGrowableRow(0)
- self.MainSizer.AddGrowableRow(1)
+ self.SizerFirmwareUpdateImageFile.Add(self.TextCtrltFirmwareUpdateImageFile,
+ flag=wx.LEFT|wx.EXPAND)
+ self.SizerFirmwareUpdateImageFile.Add(self.ButtonFirmwareUpdateImageFile,
+ flag=wx.RIGHT|wx.ALIGN_RIGHT)
+ self.SizerFirmwareUpdateImageFileBoxSizer = wx.StaticBoxSizer(wx.StaticBox(self, label=_('Update image file:')), wx.VERTICAL)
+ self.SizerFirmwareUpdateImageFileBoxSizer.AddSizer(self.SizerFirmwareUpdateImageFile, flag=wx.EXPAND)
- # Populate Update image file sizer
- self.SizerFirmwareUpdateImageFile.Add(self.StaticTextFirmwareUpdateImageFile, border=20,
- flag=wx.TOP|wx.LEFT)
- self.SizerFirmwareUpdateImageFile.Add((0,0))
- self.SizerFirmwareUpdateImageFile.Add(self.TextCtrltFirmwareUpdateImageFile, border=20,
- flag=wx.LEFT)
- self.SizerFirmwareUpdateImageFile.Add(self.ButtonFirmwareUpdateImageFile, border=20,
- flag=wx.RIGHT|wx.ALIGN_RIGHT)
+
+ self.RadioBoxFirmwareUpdateTypeChunks = wx.RadioBox(
+ self, -1, _('Update type:'), wx.DefaultPosition, wx.DefaultSize,
+ [_('Linux kernel'), _('Linux DTB'), _('Root file system')],
+ 1, wx.RA_SPECIFY_COLS)
+ self.RadioBoxFirmwareUpdateTypeChunks.SetSelection(2)
- # Populate Sizer for update type and chunks size
- self.SizerFirmwareUpdateTypeChunks.Add(self.StaticTextFirmwareUpdateType, border=20,
- flag=wx.TOP|wx.LEFT)
- self.SizerFirmwareUpdateTypeChunks.Add(self.StaticTextFirmwareUpdateChunksSize, border=20,
- flag=wx.TOP|wx.LEFT)
- self.SizerFirmwareUpdateTypeChunks.Add(self.RadioButtonFirmwareUpdateTypeLinuxKernel, border=20,
- flag=wx.LEFT)
- self.SizerFirmwareUpdateTypeChunks.Add(self.SpinCtrlFirmwareUpdateChunksSize, border=20,
- flag=wx.LEFT)
- self.SizerFirmwareUpdateTypeChunks.Add(self.RadioButtonFirmwareUpdateTypeLinuxDTB, border=20,
- flag=wx.LEFT)
- self.SizerFirmwareUpdateTypeChunks.Add(self.CheckBoxFirmwareUpdateReboot,border=20,
- flag=wx.LEFT)
- self.SizerFirmwareUpdateTypeChunks.Add(self.RadioButtonFirmwareUpdateTypeRootFs, border=20,
- flag=wx.LEFT)
- self.SizerFirmwareUpdateTypeChunks.Add(self.ButtonSizer, border=20, flag=wx.ALIGN_RIGHT|wx.RIGHT)
+ self.SizerFirmwareUpdateSizeChunks = wx.StaticBoxSizer(wx.StaticBox(self, label=_('Chunks size in KiB:')), wx.VERTICAL)
+ self.SizerFirmwareUpdateSizeChunks.Add(self.SpinCtrlFirmwareUpdateChunksSize,
+ flag=wx.EXPAND|wx.ALL)
- # Make the rows and columns growable
- self.SizerFirmwareUpdateImageFile.AddGrowableCol(0)
- self.SizerFirmwareUpdateImageFile.AddGrowableCol(1)
- self.SizerFirmwareUpdateImageFile.AddGrowableRow(0)
- self.SizerFirmwareUpdateImageFile.AddGrowableRow(1)
- self.SizerFirmwareUpdateTypeChunks.AddGrowableCol(0)
- self.SizerFirmwareUpdateTypeChunks.AddGrowableCol(1)
+ self.SizerFirmwareUpdateChunks = wx.FlexGridSizer(cols=2, rows=1)
+ self.SizerFirmwareUpdateChunks.AddGrowableCol(0)
+ self.SizerFirmwareUpdateChunks.AddGrowableCol(1)
+ self.SizerFirmwareUpdateChunks.Add(self.RadioBoxFirmwareUpdateTypeChunks, flag=wx.EXPAND|wx.RIGHT, border=20)
+ self.SizerFirmwareUpdateChunks.Add(self.SizerFirmwareUpdateSizeChunks, flag=wx.EXPAND)
+
+ self.MainSizer = wx.FlexGridSizer(cols=1, rows=3)
+ self.MainSizer.AddGrowableCol(0)
+ self.MainSizer.AddGrowableRow(1)
+ self.MainSizer.AddSizer(self.SizerFirmwareUpdateImageFileBoxSizer, flag=wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, border=20)
+ self.MainSizer.AddSizer(self.SizerFirmwareUpdateChunks, flag=wx.EXPAND|wx.LEFT|wx.TOP|wx.RIGHT, border=20)
+ self.MainSizer.AddSizer(self.ButtonSizer, flag=wx.ALIGN_RIGHT|wx.ALL, border=20)
+
# Set the main sizer
+ self.MainSizer.SetSizeHints(self)
self.SetSizer(self.MainSizer)
- def __init__(self, parent):
- self._init_ctrls(parent)
-
def OnButtonFirmwareUpdateImageFile(self, event):
dlg = wx.FileDialog(self, _("Choose a firmware image file"), expanduser("~"), "", "*", wx.OPEN)
if dlg.ShowModal() == wx.ID_OK:
@@ -125,17 +98,11 @@
return self.TextCtrltFirmwareUpdateImageFile.GetValue()
def GetFirmwareUpdateType(self):
- if self.RadioButtonFirmwareUpdateTypeLinuxKernel.GetValue() == True:
- return 1
- elif self.RadioButtonFirmwareUpdateTypeLinuxDTB.GetValue() == True:
- return 2
- elif self.RadioButtonFirmwareUpdateTypeRootFs.GetValue() == True:
- return 3
- else:
+ res = self.RadioBoxFirmwareUpdateTypeChunks.GetSelection()
+ if res == wx.NOT_FOUND:
return 0
+ return res+1
def GetChunksSize(self):
return self.SpinCtrlFirmwareUpdateChunksSize.GetValue()*1024
- def GetReboot(self):
- return self.CheckBoxFirmwareUpdateReboot.GetValue()
--- a/HostFirmwareUpdater.py Wed Apr 11 13:06:58 2018 +0200
+++ b/HostFirmwareUpdater.py Tue Dec 18 14:43:49 2018 +0100
@@ -33,109 +33,98 @@
import os
import hashlib
-import threading
-from time import sleep
-import wx
-WAIT_BEFORE_FEED_SEC = 5
UPDATE_SCRIPT_TIMEOUT = 600
class HostFirmwareUpdater(object):
# Create a new HostFirmwareUpdater
- def __init__(self, _connector, firmwareImagePath, updateType, chunksSize, reboot, logger):
+ def __init__(self, controller, firmwareImagePath, updateType, chunksSize, dialog):
self.Reset()
- self._connector = _connector
self.firmwareImagePath = firmwareImagePath
self.updateType = updateType
self.chunksSize = chunksSize
- self.reboot = reboot
- self.logger = logger
- self.logger.write(_("HostFirmwareUpdater init.\n"))
- self.threadUpdateScript = None
- self.runUpdateScriptStatus = None
- self.runUpdateScriptTextError = None
+ self.controller = controller
+ self.dialog = dialog
+ self.controller.logger.write(_("HostFirmwareUpdater init.\n"))
# Reset HostFirmwareUpdater internal variables
def Reset(self):
self.Running = 0
def update(self):
- self.logger.write(_("HostFirmwareUpdater update.\n"))
+ self.controller.logger.write(_("HostFirmwareUpdater update.\n"))
self.firmwareImageFile = open(self.firmwareImagePath, "rb")
# Read the image file
self.imageData = self.firmwareImageFile.read()
self.firmwareImageFileSize = os.stat(self.firmwareImagePath).st_size
- self.logger.write(_("Firmware image %s size: %d\n")%(self.firmwareImagePath, self.firmwareImageFileSize))
+ self.controller.logger.write(_("Firmware image %s size: %d\n")%(self.firmwareImagePath, self.firmwareImageFileSize))
# Note Pyro exceptions are already caught by catcher_func and PyroCatcher in PyroProxyProxy
# Create the necessary files on the target
self._CreateFirmwareImageFileSizeFile()
self._CreateFirmwareImageFileSizeMD5File()
self._CreateFirmwareImageFileMD5File()
- # Create and start the thread for the update script
- self.threadUpdateScript = threading.Thread(target=self._RunUpdateScript)
- self.threadUpdateScript.start()
- # Waiting some time for the update script launching
- self.logger.write(_("Waiting %s s until the update script is running...\n")%WAIT_BEFORE_FEED_SEC)
- sleep(WAIT_BEFORE_FEED_SEC)
+ # start the update script
+ status, textError = self.controller._connector.RunUpdateScript(self.updateType)
+ if not status :
+ raise Exception(textError)
# The update script is now running: Feeding the update script with firmware image data
self._RunFeedPipe()
- # Wait the end of the script
- self.threadUpdateScript.join(timeout = UPDATE_SCRIPT_TIMEOUT)
- # Here, the update is successful, reboot?
- if self.reboot:
- self._RebootTarget()
-
+
def _CreateFirmwareImageFileSizeFile(self):
# Note Pyro exceptions are already caught by catcher_func and PyroCatcher in PyroProxyProxy
- status, textError = self._connector.CreateFirmwareImageFileSizeFile(self.firmwareImageFileSize)
+ status, textError = self.controller._connector.CreateFirmwareImageFileSizeFile(self.firmwareImageFileSize)
if not status :
raise Exception(textError)
def _CreateFirmwareImageFileSizeMD5File(self):
# Note Pyro exceptions are already caught by catcher_func and PyroCatcher in PyroProxyProxy
self.firmwareImageFileMD5Size = hashlib.md5("%s\n"%self.firmwareImageFileSize).hexdigest()
- self.logger.write(_("Firmware image size md5: %s\n")%(self.firmwareImageFileMD5Size))
- status, textError = self._connector.CreateFirmwareImageFileSizeMD5File(self.firmwareImageFileMD5Size)
+ self.controller.logger.write(_("Firmware image size md5: %s\n")%(self.firmwareImageFileMD5Size))
+ status, textError = self.controller._connector.CreateFirmwareImageFileSizeMD5File(self.firmwareImageFileMD5Size)
if not status :
raise Exception(textError)
def _CreateFirmwareImageFileMD5File(self):
# Note Pyro exceptions are already caught by catcher_func and PyroCatcher in PyroProxyProxy
self.firmwareImageFileMD5 = hashlib.md5(self.imageData).hexdigest()
- self.logger.write(_("Firmware image %s md5: %s\n")%(self.firmwareImagePath, self.firmwareImageFileMD5))
- status, textError = self._connector.CreateFirmwareImageFileMD5File(self.firmwareImageFileMD5)
+ self.controller.logger.write(_("Firmware image %s md5: %s\n")%(self.firmwareImagePath, self.firmwareImageFileMD5))
+ status, textError = self.controller._connector.CreateFirmwareImageFileMD5File(self.firmwareImageFileMD5)
if not status :
raise Exception(textError)
- def _RunUpdateScript(self):
- # Put the update script run status in class attributes because,
- # since we are in a child thread, exceptions thrown in this one are painful to catch.
- # The update script run status will be checked on joining this thread.
- self.runUpdateScriptStatus, self.runUpdateScriptTextError = self._connector.RunUpdateScript(self.updateType)
-
def _RunFeedPipe(self):
# Check if a multiple chunks transfer is needed
if self.firmwareImageFileSize <= self.chunksSize :
# Only a single chunk transfer is needed
isLastChunk = True
chunksSize = self.firmwareImageFileSize
- self.logger.write(_("Single chunk transfer\n"))
+ self.controller.logger.write(_("Single chunk transfer\n"))
else:
# Multiple chunks transfer is needed
isLastChunk = False
chunksSize = self.chunksSize
- self.logger.write(_("Multiple chunks transfer\n"))
+ self.controller.logger.write(_("Multiple chunks transfer\n"))
# Start the image transfer
transferedBytes = 0
while transferedBytes < self.firmwareImageFileSize:
+
+ # User feedback as percentage
+ keepGoing, _skip = self.dialog.Update(
+ transferedBytes * 100 / self.firmwareImageFileSize)
+
+ if not keepGoing:
+ status = False
+ textError = _("Canceled")
+ raise Exception(textError)
+
chunkData = self.imageData[transferedBytes:transferedBytes + chunksSize]
- self.logger.write(_("Transfer chunk, size: %d\n")%(chunksSize))
- status, textError = self._connector.RunFeedPipe(chunkData, isLastChunk, chunksSize)
+ status, textError = self.controller._connector.RunFeedPipe(chunkData, isLastChunk, chunksSize)
if not status :
break
transferedBytes = transferedBytes + chunksSize
+
# Detect if the next chunk is the last chunk
if (self.firmwareImageFileSize - transferedBytes) <= self.chunksSize:
isLastChunk = True
@@ -143,11 +132,10 @@
# Check the transfer and the update status
if not status :
- if self.runUpdateScriptTextError != "" and not self.runUpdateScriptStatus:
- textError = "Update script message: " + self.runUpdateScriptTextError + "\n" + textError
raise Exception(textError)
else:
- self.logger.write(_("Firmware update log: \n\n") + textError + "\nFirmware update successful.")
+ self.dialog.Update(100,_("Firmware update successful."))
+ self.controller.logger.write(_("Firmware update log: \n\n") + textError + "\nFirmware update successful.\n")
- def _RebootTarget(self):
- self._connector.RebootTarget()
+ def RebootTarget(self):
+ self.controller._connector.RebootTarget()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBACnet.py Tue Dec 18 14:43:49 2018 +0100
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from bacnet import bacnet as BacnetModule
+from bacnet.bacnet import RootClass
+from LPCArch import GetLPCArch
+
+BacnetModule.BACNET_VENDOR_ID = 1071
+BacnetModule.BACNET_VENDOR_NAME = "Smarteh Company"
+BacnetModule.BACNET_DEVICE_MODEL_NAME = GetLPCArch()
+
--- a/LPCBus.py Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus.py Tue Dec 18 14:43:49 2018 +0100
@@ -24,7 +24,8 @@
for section in ["decl", "init", "retrieve", "publish", "cleanup"]}
for bus in Busses}
-LPCBusLDFLAGS = { "MC9:On Board" : "-lmbrtu" }
+# This is in case some bus has some special LDFLAGS
+LPCBusLDFLAGS = {} # ex: { "MC9:On Board" : "-lonboard" }
import os
from plcopen.structures import LOCATIONDATATYPES
--- a/LPCBus/MC9_Devices_cleanup.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_Devices_cleanup.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,6 +1,8 @@
+
+UART_task_active = 0;
+rt_task_resume(&UART_task);
rt_task_delete(&UART_task);
rt_task_join(&UART_task);
closeserial(UART_fd);
-gpio_close(RS485_GPIO_dev);
rt_mutex_delete(&UART_WriteMutex);
rt_mutex_delete(&UART_ReadMutex);
--- a/LPCBus/MC9_Devices_decl.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_Devices_decl.c Tue Dec 18 14:43:49 2018 +0100
@@ -5,9 +5,9 @@
#include <fcntl.h>
#include <sys/select.h>
-#include <native/task.h>
-#include <native/mutex.h>
-#include <native/timer.h>
+#include <alchemy/task.h>
+#include <alchemy/mutex.h>
+#include <alchemy/timer.h>
#include "beremiz.h"
@@ -20,146 +20,6 @@
perror("closeserial()");
}
-/*------------------------- GPIO -------------------------------------*/
-/* from armadeus/target/packages/as_devices/c/as_gpio* */
-
-//#ifdef DEBUG
-# define ERROR(fmt, ...) printf(fmt, ##__VA_ARGS__)
-//#else
-//# define ERROR(fmt, ...) /*fmt, ##__VA_ARGS__*/
-//#endif
-
-struct gpio_device {
- int port_num;
- int pin_file; /* pin file for 2.6.29 interface*/
-};
-
-struct gpio_device *RS485_GPIO_dev;
-
-static int write_file_bool(int fd, int value)
-{
- int ret;
-
- ret = write(fd, value?"1":"0", 1);
- if (ret < 0) {
- ERROR("write error\n");
- return ret;
- }
- if (lseek(fd, 0, SEEK_SET) < 0) {
- ERROR("lseek error\n");
- return ret;
- }
-
- return ret;
-}
-
-#define BUFF_SIZE 256
-static struct gpio_device *gpio_open(int aGpioNum)
-{
- struct gpio_device *dev;
- int pin_file;
- int export_file;
- int gpio_dir_fd;
- int retval;
- char buf[BUFF_SIZE];
- int ret = 0;
-
- export_file = open("/sys/class/gpio/export", O_WRONLY);
- if (export_file < 0) {
- ERROR("Can't open /sys/class/gpio/export\nBe sure that gpiolib is under your kernel\n");
- return NULL;
- }
-
- snprintf(buf, BUFF_SIZE, "%%d", aGpioNum);
- retval = write(export_file, buf, strlen(buf));
- close(export_file);
- if (retval < 0) {
- ERROR("/sys/class/gpio/export can't be written\n");
- return NULL;
- }
-
- snprintf(buf, BUFF_SIZE, "/sys/class/gpio/gpio%%d/direction", aGpioNum);
- gpio_dir_fd = open(buf, O_WRONLY);
- if (gpio_dir_fd < 0) {
- ERROR("Can't open gpio%%d direction\n", aGpioNum);
- return NULL;
- }
-
- ret = write(gpio_dir_fd, "out", 3);
- close(gpio_dir_fd);
- if (ret < 0){
- ERROR("Error writing direction\n");
- return NULL;
- }
-
- snprintf(buf, BUFF_SIZE, "/sys/class/gpio/gpio%%d/value", aGpioNum);
- pin_file = open(buf, O_RDWR);
- if (pin_file < 0) {
- ERROR("Can't export gpio number %%d\n", aGpioNum);
- return NULL;
- }
-
- dev = malloc(sizeof(struct gpio_device));
- if (dev == NULL) {
- ERROR("Can't allocate gpio_device structure\n");
- close(pin_file);
- return NULL;
- }
-
- dev->port_num = aGpioNum;
- dev->pin_file = pin_file;
-
- return dev;
-}
-
-static int gpio_close(struct gpio_device *aDev)
-{
- int unexport_file;
- char buf[BUFF_SIZE];
- int retval;
-
- if(aDev == NULL){
- ERROR("device is NULL\n");
- return -1;
- }
-
- unexport_file = open("/sys/class/gpio/unexport", O_WRONLY);
- if (unexport_file < 0) {
- ERROR("Can't open /sys/class/gpio/unexport\nBe sure that gpiolib is under your kernel\n");
- return -1;
- }
-
- snprintf(buf, BUFF_SIZE, "%%d", aDev->port_num);
- retval = write(unexport_file, buf, strlen(buf));
- close(unexport_file);
- if (retval < 0) {
- ERROR("/sys/class/gpio/unexport can't be written\n");
- return -1;
- }
-
- close(aDev->pin_file);
-
- return 0;
-}
-
-static int gpio_set_pin_value(struct gpio_device *aDev, int aValue)
-{
- int pin_file = aDev->pin_file;
- int retval;
-
- retval = write_file_bool(pin_file, aValue);
- if (retval < 0) {
- ERROR("Can't write value\n");
- close(pin_file);
- return -1;
- }
-
- return aValue;
-}
-
-#define TransmitMode() gpio_set_pin_value(RS485_GPIO_dev, 1)
-#define RecieveMode() gpio_set_pin_value(RS485_GPIO_dev, 0)
-
/*--------------------------- Serial Port handling ---------------------------*/
int openserial(char *devicename, unsigned long baudrate)
@@ -210,8 +70,6 @@
return 0;
}
- TransmitMode();
-
return fd;
}
@@ -270,6 +128,7 @@
static RT_TASK UART_task;
static RT_MUTEX UART_WriteMutex;
static RT_MUTEX UART_ReadMutex;
+static int UART_task_active;
void UART_task_proc(void *arg)
{
@@ -278,7 +137,11 @@
uint64_t actTime;
static uint64_t lastCommTime=0;
- while (rt_task_sleep_until(TM_INFINITE) == -EINTR){
+ while (UART_task_active){
+ rt_task_suspend(NULL);
+ if(!UART_task_active)
+ break;
+
// Communicate only with initialised UART devices
if(uartPortDevices[i] != NULL)
{
@@ -443,7 +306,6 @@
fd_set set;
struct timeval timeout;
int rv;
- RTIME now;
int count = 0;
char tmp[uartBufSize];
@@ -455,21 +317,10 @@
tcflush(UART_fd, TCIOFLUSH);
- now = rt_timer_read();
-
if(write(UART_fd, tmp, uartBufSize) != uartBufSize){
goto UARTDevfail;
}
- /* Sleep until transmission completes + 0.5ms safety */
- while(rt_task_sleep_until(
- now + rt_timer_ns2ticks(
- 1000000000LL * uartBufSize * 10 / uartBaudrate
- + 500000)) == -EINTR);
-
- /* Turn to listen mode*/
- RecieveMode();
-
FD_ZERO(&set); /* clear the set */
FD_SET(UART_fd, &set); /* add our file descriptor to the set */
@@ -495,9 +346,6 @@
}
}
- /* Turn to transmit mode*/
- TransmitMode();
-
/* Copy received buffer */
if((count == uartBufSize) && (tmp[uartBufSize-TAIL_LEN] == address)){
if(ChecksumValid((unsigned char*)tmp+1, uartBufSize)){
--- a/LPCBus/MC9_Devices_init.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_Devices_init.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,6 +1,5 @@
int err;
char *serialdev = "/dev/ttyAPP1";
-int RS485_GPIO_NUM = 102;
uartDevWriteBuf_plc_state = EMPTY;
uartDevReadBuf_plc_state = EMPTY;
@@ -27,12 +26,6 @@
if((err = rt_mutex_create (&UART_ReadMutex, "UART_ReadMutex")))
return err;
-RS485_GPIO_dev = gpio_open(RS485_GPIO_NUM);
-if (!RS485_GPIO_dev) {
- fprintf(stderr, "Error while initializing RS485 GPIO.\n");
- return 1;
-}
-
UART_fd = openserial(serialdev, uartBaudrate); /* uartBaudrate is initialized from Composer */
if (!UART_fd) {
fprintf(stderr, "Error while initializing %%s.\n", serialdev);
@@ -44,7 +37,9 @@
else
InitUartPortDevices_shortBuffer();
-if((err = rt_task_create(&UART_task, "UART_task", 0, 50, T_JOINABLE)))
+UART_task_active = 1;
+
+if((err = rt_task_create(&UART_task, "UART_task", 0, 0, T_JOINABLE)))
return err;
if((err = rt_task_start(&UART_task, &UART_task_proc, NULL)))
--- a/LPCBus/MC9_Devices_publish.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_Devices_publish.c Tue Dec 18 14:43:49 2018 +0100
@@ -12,5 +12,5 @@
uartDevWriteBuf_plc_state = FULL;
/* wakeup task */
- rt_task_unblock(&UART_task);
+ rt_task_resume(&UART_task);
}
--- a/LPCBus/MC9_OnBoard_cleanup.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_OnBoard_cleanup.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,14 +1,6 @@
-mbmrtu_cleanup();
-rt_task_delete(&RTU_UART_task);
-rt_task_join(&RTU_UART_task);
-rt_task_delete(&RTU_task);
-rt_task_join(&RTU_task);
-rt_mutex_delete(&RTU_BuffMutex);
-gpio_close(RTU_GPIO_dev);
-
#ifdef ONBOARD_I2C
if(onboardbusfd!=-1)
- rt_dev_close(onboardbusfd);
+ close(onboardbusfd);
#endif /* ONBOARD_I2C */
#ifdef CAN0_EN_GPIO_0_21
--- a/LPCBus/MC9_OnBoard_decl.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_OnBoard_decl.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,10 +1,5 @@
-
-#include <native/task.h>
-#include <native/mutex.h>
-#include <native/timer.h>
#include <unistd.h>
#include <fcntl.h>
-#include <rtdm/rtdm.h>
#include "beremiz.h"
/*------------------------- GPIO -------------------------------------*/
@@ -21,7 +16,6 @@
int pin_file; /* pin file for 2.6.29 interface*/
};
-struct gpio_device *RTU_GPIO_dev;
struct gpio_device *RUN_LED_dev;
#ifdef CAN0_EN_GPIO_0_21
struct gpio_device *CAN0_EN_dev;
@@ -153,204 +147,16 @@
return 0;
}
-
-#define REG_DISCRETE_START 0 /**< Input discrete start address */
-#define REG_DISCRETE_NREGS 1024 /**< 1024 bits (type: single bit, Read only) */
-
-#define REG_COILS_START 0 /**< Coils start address */
-#define REG_COILS_NREGS 1024 /**< 1024 bits (type: single bit, Read/Write) */
-
-#define REG_INPUT_START 0 /**< Input registers start address */
-#define REG_INPUT_NREGS 1024 /**< 1024 words (type: 16-bit word, Read only) */
-
-#define REG_HOLDING_START 0 /**< Holding registers start address */
-#define REG_HOLDING_NREGS 1024 /**< 1024 words (type: 16-bit word, Read/Write) */
-
-#define MAX_MOD_RTU_DEVICES 16
-
-typedef struct _mbRtuRdHoldingRegs {
- unsigned int use;
- unsigned short startAddr;
- unsigned char length;
- short* buffer;
-} mbRtuRdHoldingRegs;
-
-typedef struct _mbRtuRdDiscInputs {
- unsigned int use;
- unsigned short startAddr;
- unsigned short length;
- char* buffer;
-// unsigned short* buffer;
-} mbRtuRdDiscInputs;
-
-typedef struct _mbRtuRdCoils {
- unsigned int use;
- unsigned short startAddr;
- unsigned short length;
- char* buffer;
-} mbRtuRdCoils;
-
-typedef struct _mbRtuWrSingleCoil {
- unsigned int use;
- unsigned short startAddr;
- char* buffer;
-} mbRtuWrSingleCoil;
-
-typedef struct _mbRtuWrCoils {
- unsigned int use;
- unsigned short startAddr;
- unsigned short length;
- char* buffer;
-} mbRtuWrCoils;
-
-typedef struct _mbRtuRdInputRegs {
- unsigned int use;
- unsigned short startAddr;
- unsigned char length;
- short* buffer;
-} mbRtuRdInputRegs;
-
-typedef struct _mbRtuWrSingleReg {
- unsigned int use;
- unsigned short startAddr;
- short* buffer;
-} mbRtuWrSingleReg;
-
-typedef struct _mbRtuWrMultiRegs {
- unsigned int use;
- unsigned short startAddr;
- unsigned char length;
- short* buffer;
-} mbRtuWrMultiRegs;
-
-typedef struct _mbRtuSlaveConfig {
- unsigned char slaveAddr;
- mbRtuRdDiscInputs rdDiscInputs;
- mbRtuRdCoils rdCoils;
- mbRtuWrSingleCoil wrSingleCoil;
- mbRtuWrCoils wrCoils;
- mbRtuRdInputRegs rdInputRegs;
- mbRtuRdHoldingRegs rdHoldingRegs;
- mbRtuWrSingleReg wrSingleReg;
- mbRtuWrMultiRegs wrMultiRegs;
-} mbRtuSlaveConfig;
-
+/* TODO : DELETE !... but keep this until composer stops sending code snippets for mbrtu */
typedef enum
{
MB_PAR_ODD = 0, /**< ODD parity. */
MB_PAR_EVEN = 1, /**< Even parity. */
MB_PAR_NONE = 2 /**< No parity. */
} eMBSerialParity;
-
-mbRtuSlaveConfig mbRtuSlaveDev[MAX_MOD_RTU_DEVICES];/**< Tables containing information about connected Modbus network devices (initialized by Composer) */
-commTimer mbRtuDevTim[MAX_MOD_RTU_DEVICES]; /**< Table of timers (one for each position) */
-short usRegInputValue[REG_INPUT_NREGS]; /**< Array of Modbus input registers */
-short usRegHoldingValue[REG_HOLDING_NREGS]; /**< Array of Modbus holding registers */
-char ubCoilValue[REG_COILS_NREGS/8]; /**< Array of Modbus coils (8 coils per byte) */
-char ubRegDiscreteValue[REG_DISCRETE_NREGS/8]; /**< Array of Modbus discrete inputs (8 inputs per byte) */
unsigned long mbBaudRate = 115200; /**< Modbus baud-rate setting: 9600, 19200, 38400, 57600, 115200 */
eMBSerialParity mbParity = MB_PAR_NONE; /**< Modbus parity setting: odd, even, none */
-/* prototypes for functions defined in shared library */
-int mbmrtu_init(unsigned long ulBaudRate, eMBSerialParity eParity);
-void mbmrtu_BusUpdate(int);
-int mbmrtu_cleanup(void);
-
-static RT_TASK RTU_UART_task;
-static RT_TASK RTU_task;
-static RT_MUTEX RTU_BuffMutex;
-
-void LockMBRTUBuffer(void){
- while ( rt_mutex_acquire(&RTU_BuffMutex, TM_INFINITE ) == -EINTR);
-}
-void UnLockMBRTUBuffer(void){
- rt_mutex_release(&RTU_BuffMutex);
-}
-
-typedef struct {
- void*(*RTU_UART_task_proc)(void *);
- void* xSerHdl;
-} MB_xeno_task_adaptor_t;
-
-static MB_xeno_task_adaptor_t MB_xeno_task_adaptor_data;
-
-void MB_xeno_task_adaptor(void* param)
-{
- MB_xeno_task_adaptor_t *d = param;
- d->RTU_UART_task_proc(d->xSerHdl);
-}
-
-int CreateMBRTUSerialTask(
- void*(*RTU_UART_task_proc)(void *),
- void* param)
-{
- int err;
-
- MB_xeno_task_adaptor_data.RTU_UART_task_proc = RTU_UART_task_proc;
- MB_xeno_task_adaptor_data.xSerHdl = param;
-
- if((err = rt_task_start(&RTU_UART_task,
- MB_xeno_task_adaptor,
- &MB_xeno_task_adaptor_data)) != 0)
- return err;
- return 0;
-}
-
-#define nsTOus(ns) (ns/1000L)
-#define nsTOms(ns) (ns/1000000L)
-#define INVALID_RTU_ADDR 255 /* Used when no Modbus RTU slave device is present */
-static void mbmrtu_BusUpdate_proc(void *param){
- uint64_t actTime;
-
- while (rt_task_sleep_until(TM_INFINITE) == -EINTR){
- int i;
- for(i=0;i<MAX_MOD_RTU_DEVICES;i++)
- {
- if(mbRtuSlaveDev[i].slaveAddr != INVALID_RTU_ADDR)
- {
- if(mbRtuDevTim[i].status != TIM_DISABLED)
- {
- actTime = (uint64_t)nsTOms(rt_timer_read());
- mbRtuDevTim[i].actValue += actTime - mbRtuDevTim[i].oldTime;
- mbRtuDevTim[i].oldTime = actTime;
-
- if(mbRtuDevTim[i].actValue < mbRtuDevTim[i].toValue)
- mbRtuDevTim[i].status = TIM_EN_RUNNING;
- else
- mbRtuDevTim[i].status = TIM_EN_EXPIRED;
- }
- /* Check if communication depends on timer - if it does, check timer status */
- if((mbRtuDevTim[i].status == TIM_DISABLED) || (mbRtuDevTim[i].status == TIM_EN_EXPIRED))
- {
- mbmrtu_BusUpdate(i);
-
- /* If timer is enabled, reset it's value, otherwise keep it disabled */
- if(mbRtuDevTim[i].status != TIM_DISABLED)
- {
- mbRtuDevTim[i].actValue = 0; /* Reset timer value */
- mbRtuDevTim[i].status = TIM_EN_RUNNING;
- }
- else /* Keep timer disabled */
- mbRtuDevTim[i].status = TIM_DISABLED;
- }
- }
- }
-
- }
-}
-
-RTIME now;
-void TransmitMode(void){
- gpio_set_pin_value(RTU_GPIO_dev, 1);
- now = rt_timer_read();
-}
-void RecieveMode(int us){
- while(rt_task_sleep_until(
- now + rt_timer_ns2ticks(1000LL*us)
- ) == -EINTR);
- gpio_set_pin_value(RTU_GPIO_dev, 0);
-}
-
#ifdef ONBOARD_I2C
#define MAX_ONBOARD_DEVICES 2
#define ONBOARD_READ_BUFSIZE 30
--- a/LPCBus/MC9_OnBoard_init.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_OnBoard_init.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,13 +1,7 @@
-#define ONBOARDDEVFILENAME "onBoard"
+#define ONBOARDDEVFILENAME "/dev/rtdm/onBoard"
int err;
-bzero(&usRegInputValue , sizeof(usRegInputValue ));
-bzero(&usRegHoldingValue , sizeof(usRegHoldingValue ));
-bzero(&ubCoilValue , sizeof(ubCoilValue ));
-bzero(&ubRegDiscreteValue, sizeof(ubRegDiscreteValue));
-bzero(&mbRtuSlaveDev , sizeof(mbRtuSlaveDev ));
-bzero(&mbRtuDevTim , sizeof(mbRtuDevTim ));
#ifdef ONBOARD_I2C
bzero(&onBoardReadBuf , sizeof(onBoardReadBuf_t ));
bzero(&onBoardWriteBuf , sizeof(onBoardWriteBuf_t ));
@@ -28,41 +22,22 @@
gpio_set_pin_value(CAN1_EN_dev, 0);
#endif /* CAN1_EN_GPIO_0_17 */
-RTU_GPIO_dev = gpio_open(111);
-if (!RTU_GPIO_dev) {
- fprintf(stderr, "Error while initializing RTU GPIO.\n");
- return 1;
-}
-if((err = rt_mutex_create (&RTU_BuffMutex, "RTU_BuffMutex")))
- return err;
-
-if((err = rt_task_create(&RTU_UART_task, "RTU_UART_task", 0, 50, T_JOINABLE)))
- return err;
-
-mbmrtu_init(mbBaudRate, mbParity);
-
-if((err = rt_task_create(&RTU_task, "RTU_task", 0, 50, T_JOINABLE)))
- return err;
-
-if(rt_task_start(&RTU_task, mbmrtu_BusUpdate_proc, NULL))
- return err;
-
#ifdef ONBOARD_I2C
unsigned char i;
for(i=0; i<MAX_ONBOARD_DEVICES; i++) {
switch(onBoardDev[i][1]) {
case 1:
/* OnBoard I2C bus */
- onboardbusfd = rt_dev_open(ONBOARDDEVFILENAME, 0);
+ onboardbusfd = open(ONBOARDDEVFILENAME, 0);
if(onboardbusfd < 0) {
printf("can't open %%s rtdm device, %%s\n", ONBOARDDEVFILENAME,
strerror(-onboardbusfd));
return onboardbusfd;
}
- err = rt_dev_ioctl(onboardbusfd, RTSMT_ONBOARD_RTIOC_INIT, &onBoardBusInit);
+ err = ioctl(onboardbusfd, RTSMT_ONBOARD_RTIOC_INIT, &onBoardBusInit);
if(err) {
printf("error while RTSMT_ONBOARD_RTIOC_INIT, %%s\n", strerror(-err));
- rt_dev_close(onboardbusfd);
+ close(onboardbusfd);
return err;
}
break;
--- a/LPCBus/MC9_OnBoard_publish.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_OnBoard_publish.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,12 +1,6 @@
-
%(publish_code)s
-UnLockMBRTUBuffer();
-
-/* wakeup task */
-rt_task_unblock(&RTU_task);
-
#ifdef ONBOARD_I2C
if(onboardbusfd!=-1)
- rt_dev_ioctl(onboardbusfd, RTSMT_ONBOARD_RTIOC_WRITE, &onBoardWriteBuf);
+ ioctl(onboardbusfd, RTSMT_ONBOARD_RTIOC_WRITE, &onBoardWriteBuf);
#endif /* ONBOARD_I2C */
--- a/LPCBus/MC9_OnBoard_retrieve.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_OnBoard_retrieve.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,8 +1,6 @@
-LockMBRTUBuffer();
-
#ifdef ONBOARD_I2C
if(onboardbusfd!=-1)
- rt_dev_ioctl(onboardbusfd, RTSMT_ONBOARD_RTIOC_READ, &onBoardReadBuf);
+ ioctl(onboardbusfd, RTSMT_ONBOARD_RTIOC_READ, &onBoardReadBuf);
#endif /* ONBOARD_I2C */
%(retrieve_code)s
--- a/LPCBus/MC9_Right_cleanup.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_Right_cleanup.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,1 +1,1 @@
-rt_dev_close(rightbusfd);
+close(rightbusfd);
--- a/LPCBus/MC9_Right_init.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_Right_init.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,4 +1,4 @@
-#define DEVICEFILENAME "rightbus"
+#define DEVICEFILENAME "/dev/rtdm/rightbus"
bzero(&rightReadBuf, sizeof(rightReadBuf_t));
bzero(&rightWriteBuf, sizeof(rightWriteBuf_t));
@@ -10,17 +10,17 @@
%(init_code)s
int err;
-rightbusfd = rt_dev_open( DEVICEFILENAME, 0);
+rightbusfd = open( DEVICEFILENAME, 0);
if (rightbusfd < 0) {
printf("can't open %%s rtdm device, %%s\\n", DEVICEFILENAME,
strerror(-rightbusfd));
return rightbusfd;
}
-err = rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_INIT, &rightBusInit);
+err = ioctl(rightbusfd, RTSMT_RTIOC_INIT, &rightBusInit);
if (err) {
printf("error while RTSMT_RTIOC_INIT, %%s\\n",
strerror(-err));
- rt_dev_close(rightbusfd);
+ close(rightbusfd);
return err;
}
--- a/LPCBus/MC9_Right_publish.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_Right_publish.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,2 +1,2 @@
%(publish_code)s
-rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_WRITE, &rightWriteBuf);
+ioctl(rightbusfd, RTSMT_RTIOC_WRITE, &rightWriteBuf);
--- a/LPCBus/MC9_Right_retrieve.c Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCBus/MC9_Right_retrieve.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,2 +1,2 @@
-rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_READ, &rightReadBuf);
+ioctl(rightbusfd, RTSMT_RTIOC_READ, &rightReadBuf);
%(retrieve_code)s
--- a/LPCCanFestival.py Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCCanFestival.py Tue Dec 18 14:43:49 2018 +0100
@@ -12,17 +12,6 @@
from canfestival.SlaveEditor import SlaveEditor
from canfestival import canfestival
-defaultGetCFLAGS = canfestival.local_canfestival_config.getCFLAGS
-defaultGetLDFLAGS = canfestival.local_canfestival_config.getLDFLAGS
-
-def getCFLAGS(*args):
- return str(defaultGetCFLAGS(*args))
-
-def getLDFLAGS(*args):
- return str(defaultGetLDFLAGS(*args))
-
-canfestival.local_canfestival_config.getCFLAGS = getCFLAGS
-canfestival.local_canfestival_config.getLDFLAGS = getLDFLAGS
DEFAULT_SETTINGS = {
"CAN_Baudrate": "125K",
--- a/LPCExtension.py Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCExtension.py Tue Dec 18 14:43:49 2018 +0100
@@ -13,20 +13,20 @@
# _lpcmanager_path, arch, etc are defined here because
# globals() of LPCManager.py are passed to extentions
-features.libraries=[('Native', 'NativeLib.NativeLibrary')]
+features.libraries=[('Native', 'NativeLib.NativeLibrary', True)]
def _poulibpath(name):
return os.path.join(_lpcmanager_path, 'Pous', "pous"+name+".xml")
if arch in PLC_MC9_module:
- features.libraries += [('Python', 'py_ext.PythonLibrary'),
- ('RTC', SimplePOULibraryFactory(_poulibpath("RTC")))]
+ features.libraries += [('Python', 'py_ext.PythonLibrary', True),
+ ('RTC', SimplePOULibraryFactory(_poulibpath("RTC")), True)]
elif arch in PLC_GOT_module:
- features.libraries += [('Python', 'py_ext.PythonLibrary'),
- ('RTC', SimplePOULibraryFactory(_poulibpath("RTC"))),
- ('GOT', SimplePOULibraryFactory(_poulibpath("GOT")))]
+ features.libraries += [('Python', 'py_ext.PythonLibrary', True),
+ ('RTC', SimplePOULibraryFactory(_poulibpath("RTC")), True),
+ ('GOT', SimplePOULibraryFactory(_poulibpath("GOT")), True)]
else:
- features.libraries += [('LPC', SimplePOULibraryFactory(_poulibpath("LPC")))]
+ features.libraries += [('LPC', SimplePOULibraryFactory(_poulibpath("LPC")), True)]
#
# --------- Configuration Tree Nodes (CTN) catalog extension ------------
@@ -34,8 +34,10 @@
_oldcatalog = features.catalog
catalog_index = dict(zip(zip(*_oldcatalog)[0],_oldcatalog))
wanted_beremiz_features = [catalog_index[feature]
- for feature in ["modbus", "c_ext", "py_ext"]]
+ for feature in ["c_ext", "py_ext", "wxglade_hmi"]]
features.catalog = wanted_beremiz_features + [
+ ('bacnet', _('Bacnet support'), _('Map located variables over Bacnet'), 'LPCBACnet.RootClass'),
+ ('modbus', _('Modbus'), _('Map located variables over Modbus'), 'LPCModbus.RootClass'),
('LPCBus', _('LPC bus'), _('Support for Smarteh modules'), 'LPCBus.LPCBus'),
('CanOpen', _('CANOpen'), _('Support for CANopen'), 'LPCCanFestival.LPCCanOpen')]
@@ -44,9 +46,18 @@
#
import connectors
-from LPCconnector import LPC_connector_factory
+from functools import partial
-connectors.connectors["LPC"] = lambda: LPC_connector_factory
+# On demand monkey patching
+def CustomWAMPFactory(*args, **kwargs):
+ from connectors import WAMP
+ from WampAuthentication import WampSession
+ return WAMP._WAMP_connector_factory(WampSession, *args, **kwargs)
+connectors.connectors["WAMP"] = lambda:CustomWAMPFactory
+
+# TODO
+# from LPCconnector import LPC_connector_factory
+# connectors.connectors["LPC"] = lambda: LPC_connector_factory
#
# --------- Targets/Toolchains Extension ------------
@@ -64,3 +75,14 @@
"code": {"plc_MC9_main.c": targets.targets["Xenomai"]["code"]["plc_Xenomai_main.c"],
"plc_MC9_main_retain.c": os.path.join(_lpcmanager_path,
"MC9target", "plc_MC9_main_retain.c")}}
+
+#
+# --------- Custom columns function Extension ------------
+#
+
+from WampOptionsEditor import WampOptionsCellEditor
+from py_ext.PythonEditor import PythonEditor
+from wxglade_hmi import WxGladeHMI
+from WxGladeEditor import WxGladeEditor
+WxGladeHMI.EditorType = WxGladeEditor
+PythonEditor.COLUMNS_TYPE = {'Options': WampOptionsCellEditor}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCModbus.py Tue Dec 18 14:43:49 2018 +0100
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from modbus.modbus import _ModbusRTUclientPlug, _ModbusRTUslavePlug, RootClass
+
+wrong_uart_name = "ttyS0"
+good_uart_name = "ttyAPP3"
+_ModbusRTUclientPlug.XSD = _ModbusRTUclientPlug.XSD.replace(wrong_uart_name,good_uart_name)
+_ModbusRTUslavePlug.XSD = _ModbusRTUslavePlug.XSD.replace(wrong_uart_name,good_uart_name)
--- a/LPCProjectController.py Wed Apr 11 13:06:58 2018 +0200
+++ b/LPCProjectController.py Tue Dec 18 14:43:49 2018 +0100
@@ -9,9 +9,9 @@
from LPCArch import PLC_module
from FirmwareUpdateDialog import FirmwareUpdateDialog
-from dialogs import DiscoveryDialog
from HostFirmwareUpdater import HostFirmwareUpdater
+from plcopen.types_enums import ComputeConfigurationResourceName
LPCStatusMethods = [
{"bitmap": "UpdateFw",
@@ -21,9 +21,17 @@
"method": "_UpdateFw"}
]
+LPCDefaultMethods = ProjectController.DefaultMethods.copy()
+LPCDefaultMethods["_UpdateFw"]=False
+LPCMethodsFromStatus = ProjectController.MethodsFromStatus.copy()
+LPCMethodsFromStatus["Started"]["_UpdateFw"] = True
+LPCMethodsFromStatus["Stopped"]["_UpdateFw"] = True
+LPCMethodsFromStatus["Empty"]["_UpdateFw"] = True
class LPCProjectController(ProjectController):
StatusMethods = ProjectController.StatusMethods + LPCStatusMethods
+ DefaultMethods = LPCDefaultMethods
+ MethodsFromStatus = LPCMethodsFromStatus
def __init__(self, frame, logger, buildpath, arch):
self.arch = arch
@@ -59,7 +67,7 @@
dirname = ops(extrafilespath)[-1]
for name in os.listdir(extrafilespath):
zf.write(opj(extrafilespath, str(name)), opj(dirname, str(name)), zipfile.ZIP_DEFLATED)
- zf.write(self._builder.exe_path, self._builder.exe)
+ zf.write(self._builder.bin_path, self._builder.bin)
zf.write(opj(self._getBuildPath(), 'lastbuildPLC.md5'), 'lastbuildPLC.md5')
zf.close()
self.logger.write(_("xEye export file created at: %s\n") % output_file_path)
@@ -107,7 +115,7 @@
ProjectController.AddProjectDefaultConfiguration(self, config_name, res_name)
self.SetEditedResourceInfos(
- self.ComputeConfigurationResourceName(config_name, res_name),
+ ComputeConfigurationResourceName(config_name, res_name),
[{"Name": "main_task",
"Triggering": "Cyclic",
"Interval": "T#50ms",
@@ -162,7 +170,6 @@
imageFilePath = dialog.GetFirmwareImageFile()
updateType = dialog.GetFirmwareUpdateType()
chunksSize = dialog.GetChunksSize()
- reboot = dialog.GetReboot()
dialog.Destroy()
if answer == wx.ID_CANCEL:
@@ -198,49 +205,6 @@
else:
self.logger.write(_("Chunks size : %d KiB\n") % chunksSize)
- self.logger.write(_("Reboot after update : %s\n") % ("Yes" if reboot else "No"))
- # Get the target PLC URI
- # Check if an uri is already configured in the Beremiz project
- uri = self.BeremizRoot.getURI_location()
- if uri is not None and uri != "":
- self.logger.write(_("PLC URI configured in the Beremiz project will be used: %s\n") % uri)
- else:
- # PLC URI is not configured in the Beremiz project
- # Launch Service Discovery dialog
- self.logger.write(_("PLC URI is not configured in the Beremiz project. Launching the Discover dialog\n"))
- dialog = DiscoveryDialog(self.AppFrame)
- answer = dialog.ShowModal()
- uri = dialog.GetURI()
- dialog.Destroy()
-
- # Nothing choosed or cancel button
- if uri is None or answer == wx.ID_CANCEL:
- self.logger.write_error(_("Connection canceled!\n"))
- self.logger.write_error(_("Firmware update canceled!\n"))
- self.firmwareUpadateIsRunning = False
- return
-
- # Get connector from uri
- self._connector = None
- try:
- self._SetConnector(connectors.ConnectorFactory(uri, self))
- except Exception:
- self.logger.write_error(_("Exception while connecting %s!\n") % uri)
- self.logger.write_error(traceback.format_exc())
- self.logger.write_error(_("Firmware update canceled!\n"))
- self.firmwareUpadateIsRunning = False
- return
-
- # Did connection success ?
- if self._connector is None:
- # Oups.
- self.logger.write_error(_("Connection failed to %s!\n") % uri)
- self.logger.write_error(_("Firmware update canceled!\n"))
- self.firmwareUpadateIsRunning = False
- return
- else:
- self.logger.write(_("Connected.\n"))
-
# Last confirmation before firmware update
answer = wx.MessageBox(_('Are you sure to launch the firmware update for the selected PLC?'),
_('Firmware Update'), wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT,
@@ -249,20 +213,52 @@
self.logger.write_error(_("Firmware update canceled!\n"))
self.firmwareUpadateIsRunning = False
return
+
+ # do we still have a connection ?
+ if self._connector is None:
+ # Oups.
+ self.logger.write_error(_("Firmware update canceled because connection lost!\n"))
+ self.firmwareUpadateIsRunning = False
+ return
+
# Some cosmetics
self.AppFrame.Refresh()
self.AppFrame.Update()
+ dlg = wx.ProgressDialog(_("Firmware update"),
+ _("Updating firmware, please wait."),
+ maximum = 100,
+ parent=self.AppFrame,
+ style = 0
+ | wx.PD_APP_MODAL
+ | wx.PD_CAN_ABORT
+ | wx.PD_ESTIMATED_TIME
+ | wx.PD_REMAINING_TIME
+ )
+
# Lauch the firmaware update on the remote PLC
- updater = HostFirmwareUpdater(self._connector, imageFilePath, updateType, chunksSize, reboot, self.logger)
+ updater = HostFirmwareUpdater(self, imageFilePath, updateType, chunksSize, dlg)
try:
updater.update()
except Exception as e:
self.logger.write_error(str(e) + "\n")
- self.logger.write_error(_("Firmware update canceled!\n"))
+ self.logger.write_error(_("Firmware update failed!\n"))
+ if not dlg.WasCancelled():
+ dlg.Update(100, _("Firmware update failed!\n(%s)"%str(e)))
+ return
+ finally:
self.firmwareUpadateIsRunning = False
+ dlg.Destroy()
+
+
+ # Propose reboot
+ answer = wx.MessageBox(_('Firmware update requires reboot to complete. Reboot PLC now?'),
+ _('Firmware Update'), wx.YES_NO | wx.CENTRE | wx.NO_DEFAULT,
+ self.AppFrame)
+ if answer == wx.YES:
+ self.logger.write(_("Rebooting PLC.\n"))
+ updater.RebootTarget()
self._Disconnect()
return
- self._Disconnect()
- self.firmwareUpadateIsRunning = False
+
return True
--- a/MC8ProjectController.py Wed Apr 11 13:06:58 2018 +0200
+++ b/MC8ProjectController.py Tue Dec 18 14:43:49 2018 +0100
@@ -768,14 +768,11 @@
self.AbortTransferTimer = None
event.Skip()
+ # FIXME: MC8 doesn't know how to deal with any of this...
def _UpdateFw(self):
"""
Method called by user to flash the firmware of the PLC
"""
- from FirmwareUpdateDialog import FirmwareUpdateDialog
- from dialogs import DiscoveryDialog
- from HostFirmwareUpdater import HostFirmwareUpdater
-
if self.firmawreUpadateIsRunning == True:
self.logger.write_error(_("Firmware update is already running!\n"))
return
--- a/MC9target/XSD Wed Apr 11 13:06:58 2018 +0200
+++ b/MC9target/XSD Tue Dec 18 14:43:49 2018 +0100
@@ -1,9 +1,9 @@
<xsd:element name="MC9">
<xsd:complexType>
- <xsd:attribute name="Compiler" type="xsd:string" use="optional" default="arm-none-linux-gnueabi-gcc"/>
- <xsd:attribute name="CFLAGS" type="xsd:string" use="optional" default="--sysroot=../arm-none-linux-gnueabi-apf28 -I../arm-none-linux-gnueabi-apf28/usr/include/xenomai -D_GNU_SOURCE -D_REENTRANT -DHAVE_RETAIN -Wall -pipe -D__XENO__ -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-variable"/>
- <xsd:attribute name="Linker" type="xsd:string" use="optional" default="arm-none-linux-gnueabi-gcc"/>
- <xsd:attribute name="LDFLAGS" type="xsd:string" use="optional" default="--sysroot=../arm-none-linux-gnueabi-apf28 -lnative -lxenomai -lpthread -lrtdm"/>
+ <xsd:attribute name="Compiler" type="xsd:string" use="optional" default="arm-unknown-linux-gnueabi-gcc"/>
+ <xsd:attribute name="CFLAGS" type="xsd:string" use="optional" default="--sysroot=../arm-linux-gnueabi-apf28 -DHAVE_RETAIN -pipe -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-variable -I../arm-linux-gnueabi-apf28/usr/include/xenomai/cobalt -I../arm-linux-gnueabi-apf28/usr/include/xenomai -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -I../arm-linux-gnueabi-apf28/usr/include/xenomai/alchemy -D__COBALT_WRAP__ "/>
+ <xsd:attribute name="Linker" type="xsd:string" use="optional" default="arm-unknown-linux-gnueabi-gcc"/>
+ <xsd:attribute name="LDFLAGS" type="xsd:string" use="optional" default="--sysroot=../arm-linux-gnueabi-apf28 -lpthread -Wl,--no-as-needed -Wl,@../arm-linux-gnueabi-apf28/usr/lib/cobalt.wrappers -Wl,@../arm-linux-gnueabi-apf28/usr/lib/modechk.wrappers -lalchemy -lcopperplate -L../arm-linux-gnueabi-apf28/usr/lib -lcobalt -lmodechk -lpthread -lrt "/>
<xsd:attribute name="XenoConfig" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
--- a/MC9target/plc_MC9_main_retain.c Wed Apr 11 13:06:58 2018 +0200
+++ b/MC9target/plc_MC9_main_retain.c Tue Dec 18 14:43:49 2018 +0100
@@ -1,10 +1,10 @@
-#include <native/event.h>
-#include <native/mutex.h>
+#include <alchemy/event.h>
+#include <alchemy/mutex.h>
#include <rtdm/rtdm.h>
#include <rtdm/spi_apf28_rtdm_ioctl.h>
+#include <xenomai/init.h>
-#define TEST_SPI_BUS_NUMBER 2
/* SPI configurable parameters */
/* --------------------------- */
@@ -60,24 +60,24 @@
int size;
unsigned int uint;
uint = 1;
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
printf("Failed to lock CS\n");
return 0;
}
- status = rt_dev_write(fd_spi, rcmd, ARRAY_SIZE(rcmd));
+ status = write(fd_spi, rcmd, ARRAY_SIZE(rcmd));
if (status < 0) {
fprintf(stderr, "Failed to send read command. ERR : %d\n", status);
return 0;
}
uint = 0;
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) {
printf("Failed to unlock CS\n");
return 0;
}
- size = rt_dev_read(fd_spi, buf, len);
+ size = read(fd_spi, buf, len);
if (size != len) {
fprintf(stderr, "Failed to read %d bytes on the SPI bus. size : %d\n",
len, size);
@@ -89,7 +89,7 @@
int SPI_Write(void *buf, unsigned int len){
int status;
- status = rt_dev_write(fd_spi, buf, len);
+ status = write(fd_spi, buf, len);
if (status < 0) {
fprintf(stderr, "Failed to write memory. ERR : %d\n", status);
return 0;
@@ -103,7 +103,7 @@
unsigned int uint;
/* Open the SPI RTDM device */
- if ((fd_spi = rt_dev_open("spi_apf28_rtdm", TEST_SPI_BUS_NUMBER)) < 0) {
+ if ((fd_spi = open("/dev/rtdm/spi_apf28_rtdm", 0)) < 0) {
printf("rt_spi_open error\n");
return;
}
@@ -112,66 +112,66 @@
/* Clock phase */
uint = TEST_SPI_CLK_PHASE;
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPHASE_SET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_CLKPHASE_SET, &uint) < 0) {
printf("Failed to configure the clock phase\n");
return;
}
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPHASE_GET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_CLKPHASE_GET, &uint) < 0) {
printf("Failed to get the clock phase\n");
return;
}
/* Clock polarity */
uint = TEST_SPI_CLK_POLARITY;
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_SET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_SET, &uint) < 0) {
printf("Failed to configure the clock polarity\n");
return;
}
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_GET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_GET, &uint) < 0) {
printf("Failed to get the clock polarity\n");
return;
}
/* Frequency */
ulong = TEST_SPI_SPEED;
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_FREQ_SET, &ulong) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_FREQ_SET, &ulong) < 0) {
printf("Failed to configure the frequency\n");
return;
}
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_FREQ_GET, &ulong) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_FREQ_GET, &ulong) < 0) {
printf("Failed to get the frequency\n");
return;
}
/* Bits per word */
uint = TEST_SPI_BITS_PER_WORD;
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_BITSPERWORD_SET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_BITSPERWORD_SET, &uint) < 0) {
printf("Failed to configure the BPW\n");
return;
}
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_BITSPERWORD_GET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_BITSPERWORD_GET, &uint) < 0) {
printf("Failed to get the BPW\n");
return;
}
/* Chipselect */
uint = TEST_SPI_CHIPSELECT1;
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_CHIPSELECT_SET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_CHIPSELECT_SET, &uint) < 0) {
printf("Failed to configure the chip select\n");
return;
}
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_CHIPSELECT_GET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_CHIPSELECT_GET, &uint) < 0) {
printf("Failed to get the chip select\n");
return;
}
/* DMA usage definition */
uint = TEST_SPI_DMA_BYTES_MIN;
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_DMA_SET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_DMA_SET, &uint) < 0) {
printf("Failed to configure the DMA threshold\n");
return;
}
- if (rt_dev_ioctl(fd_spi, RTDM_SPI_DMA_GET, &uint) < 0) {
+ if (ioctl(fd_spi, RTDM_SPI_DMA_GET, &uint) < 0) {
printf("Failed to get the DMA threshold\n");
return;
}
@@ -194,7 +194,7 @@
0x01, 0x40,
};
- status = rt_dev_write(fd_spi, mbuf, ARRAY_SIZE(mbuf));
+ status = write(fd_spi, mbuf, ARRAY_SIZE(mbuf));
if (status < 0) {
printf("Failed to change mode. ERR : %d\n", status);
return;
@@ -206,7 +206,7 @@
void RETAIN_task_proc(void *arg)
{
- unsigned long msk = 0;
+ unsigned int msk = 0;
NVRAM_Init();
while (!rt_event_wait(&RETAIN_Event, 1, &msk, EV_ANY, TM_INFINITE)) {
if(rt_mutex_acquire(&RETAIN_Mutex, TM_INFINITE)) return;
--- a/Pous/pousGOT.xml Wed Apr 11 13:06:58 2018 +0200
+++ b/Pous/pousGOT.xml Tue Dec 18 14:43:49 2018 +0100
@@ -17,7 +17,7 @@
<types>
<dataTypes/>
<pous>
- <pou name="Backlight_dimmer" pouType="functionBlock">
+ <pou name="Set_Brightness" pouType="functionBlock">
<interface>
<inputVars>
<variable name="TRIG">
@@ -25,67 +25,97 @@
<BOOL/>
</type>
</variable>
- <variable name="TYPE_VALUE">
+ <variable name="PERCENT">
<type>
- <INT/>
- </type>
- </variable>
- <variable name="DIMM_VALUE">
- <type>
- <INT/>
+ <UINT/>
</type>
</variable>
</inputVars>
- <localVars>
- <variable name="pooll0">
- <type>
- <derived name="python_poll"/>
- </type>
- </variable>
+ <outputVars>
<variable name="ACK">
<type>
<BOOL/>
</type>
</variable>
- <variable name="RESULT">
- <type>
- <string/>
- </type>
- </variable>
- <variable name="INPUT_ARGS">
- <type>
- <string/>
- </type>
- </variable>
- <variable name="INPUT_TYPE">
+ </outputVars>
+ <localVars>
+ <variable name="eval">
<type>
- <string/>
- </type>
- </variable>
- <variable name="INPUT_VALUE">
- <type>
- <string/>
- </type>
- </variable>
- <variable name="INPUT_VALUE_CODE">
- <type>
- <string/>
- </type>
- </variable>
- <variable name="CODE">
- <type>
- <string/>
+ <derived name="python_eval"/>
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
- <xhtml:p><![CDATA[INPUT_TYPE:=INT_TO_STRING(TYPE_VALUE); INPUT_VALUE:=INT_TO_STRING(DIMM_VALUE); INPUT_ARGS:=CONCAT(INPUT_TYPE, ',', INPUT_VALUE); INPUT_VALUE_CODE:=CONCAT('PLCObject.MWProvider.SetDimmerValue(', INPUT_ARGS, ')'); pooll0(TRIG := TRIG, CODE := INPUT_VALUE_CODE, ACK => ACK, RESULT => RESULT);]]></xhtml:p>
+ <xhtml:p><![CDATA[(* Set dimmer value *)
+eval(
+ TRIG := TRIG,
+ CODE := CONCAT(
+ 'SetDimmerValue(',
+ UINT_TO_STRING(PERCENT),
+ ')'
+ ),
+ ACK => ACK
+);]]></xhtml:p>
</ST>
</body>
<documentation>
- <xhtml:p><![CDATA[Backlight_dimmer function block allows the manipulation of brightness. TYPE_VALUE ranges from 0 to 3, where 0 is no fading, 1 slowly changes brightness when lowering it, 2 slowly changes brightness when rising it and 3 slowly changes it both ways. DIMM_VALUE ranges from 0 to 26 and changes the brightness value.]]></xhtml:p>
+ <xhtml:p><![CDATA[Set backlight brightness to PERCENT on raising edge of TRIG.]]></xhtml:p>
+ </documentation>
+ </pou>
+ <pou name="Fade_Brightness" pouType="functionBlock">
+ <interface>
+ <inputVars>
+ <variable name="TRIG">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="PERCENT">
+ <type>
+ <UINT/>
+ </type>
+ </variable>
+ <variable name="TIME_MS">
+ <type>
+ <UINT/>
+ </type>
+ </variable>
+ </inputVars>
+ <outputVars>
+ <variable name="ACK">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ </outputVars>
+ <localVars>
+ <variable name="eval">
+ <type>
+ <derived name="python_eval"/>
+ </type>
+ </variable>
+ </localVars>
+ </interface>
+ <body>
+ <ST>
+ <xhtml:p><![CDATA[(* Fade dimmer value *)
+eval(
+ TRIG := TRIG,
+ CODE := CONCAT(
+ 'SetDimmerValue(',
+ UINT_TO_STRING(PERCENT),
+ ',',
+ UINT_TO_STRING(TIME_MS),
+ ')'
+ ),
+ ACK => ACK
+);]]></xhtml:p>
+ </ST>
+ </body>
+ <documentation>
+ <xhtml:p><![CDATA[Start fading backlight brightness on raising edge of TRIG, from current value to PERCENT, in TIME_MS miliseconds.]]></xhtml:p>
</documentation>
</pou>
<pou name="Buzzer" pouType="functionBlock">
@@ -98,9 +128,9 @@
</variable>
</inputVars>
<localVars>
- <variable name="pooll0">
+ <variable name="eval">
<type>
- <derived name="python_poll"/>
+ <derived name="python_eval"/>
</type>
</variable>
<variable name="ACK">
@@ -108,24 +138,19 @@
<BOOL/>
</type>
</variable>
- <variable name="RESULT">
- <type>
- <string/>
- </type>
- </variable>
- <variable name="INPUT_VALUE_OLD">
- <type>
- <string/>
- </type>
- </variable>
<variable name="TRIG">
<type>
<BOOL/>
</type>
</variable>
- <variable name="INPUT_VALUE_CODE">
+ <variable name="APPLIED_VAL">
<type>
- <string/>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="ORDERED_VAL">
+ <type>
+ <BOOL/>
</type>
</variable>
<variable name="CODE">
@@ -133,15 +158,47 @@
<string/>
</type>
</variable>
+ <variable name="rtrig">
+ <type>
+ <derived name="R_TRIG"/>
+ </type>
+ </variable>
+ <variable name="RACK">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
</localVars>
</interface>
<body>
<ST>
- <xhtml:p><![CDATA[TRIG :=TRUE; INPUT_VALUE_CODE:=CONCAT('PLCObject.MWProvider.SetBuzzerValue(', INT_TO_STRING(BOOL_TO_INT(INPUT_VALUE)), ')'); pooll0(TRIG := TRIG, CODE := INPUT_VALUE_CODE, ACK => ACK, RESULT => RESULT);]]></xhtml:p>
+ <xhtml:p><![CDATA[(* Turn buzzer on or off *)
+(* test if not already waiting for ack, and there is change to apply *)
+IF NOT(TRIG & NOT(ACK)) & (APPLIED_VAL <> INPUT_VALUE) THEN
+ TRIG := TRUE;
+ ORDERED_VAL := INPUT_VALUE;
+ CODE:=CONCAT(
+ 'SetBuzzerValue(',
+ INT_TO_STRING(BOOL_TO_INT(INPUT_VALUE)),
+ ')'
+ );
+END_IF;
+eval(
+ TRIG := TRIG,
+ CODE := CODE,
+ ACK => ACK
+);
+rtrig(CLK := ACK, Q => RACK);
+IF RACK THEN
+ TRIG := FALSE;
+ APPLIED_VAL := ORDERED_VAL;
+END_IF;
+
+]]></xhtml:p>
</ST>
</body>
<documentation>
- <xhtml:p><![CDATA[Buzzer function block provides a buzz sound]]></xhtml:p>
+ <xhtml:p><![CDATA[Turns buzzer on or off, according to input value]]></xhtml:p>
</documentation>
</pou>
</pous>
--- a/Pous/pousRTC.xml Wed Apr 11 13:06:58 2018 +0200
+++ b/Pous/pousRTC.xml Tue Dec 18 14:43:49 2018 +0100
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xsi:schemaLocation="http://www.plcopen.org/xml/tc6_0201">
<fileHeader companyName="Beremiz" productName="Beremiz" productVersion="0.0" creationDateTime="2008-12-14T16:53:26"/>
- <contentHeader name="Beremiz non-standard POUs library" modificationDateTime="2014-03-17T08:07:24">
+ <contentHeader name="Beremiz non-standard POUs library" modificationDateTime="2018-09-06T13:45:38">
<coordinateInfo>
<fbd>
<scaling x="0" y="0"/>
@@ -17,19 +17,74 @@
<types>
<dataTypes/>
<pous>
- <pou name="getRTC" pouType="functionBlock">
+ <pou name="getRTCString" pouType="functionBlock">
<interface>
+ <inputVars>
+ <variable name="TRIG">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ </inputVars>
<outputVars>
+ <variable name="ACK">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
<variable name="DT_STR">
<type>
<string/>
</type>
</variable>
+ </outputVars>
+ <localVars>
+ <variable name="eval">
+ <type>
+ <derived name="python_eval"/>
+ </type>
+ </variable>
+ </localVars>
+ </interface>
+ <body>
+ <ST>
+ <xhtml:p><![CDATA[(* Get time from RTC *)
+eval(TRIG:=TRIG, CODE:='GetRTC()', ACK => ACK, RESULT => DT_STR);]]></xhtml:p>
+ </ST>
+ </body>
+ <documentation>
+ <xhtml:p><![CDATA[Sample time from RTC on raising edge of TRIG. Outputs a formated string in DT_STR and sets ACK to TRUE when output is ready.
+Format:
+ YYYY-mm-dd HH:MM:SS w v
+
+Last two numbers are :
+ w: week day
+ v: valid flag
+
+Example:
+ 2018-07-28 11:24:07 6 1]]></xhtml:p>
+ </documentation>
+ </pou>
+ <pou name="getRTC" pouType="functionBlock">
+ <interface>
+ <inputVars>
+ <variable name="TRIG">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
+ </inputVars>
+ <outputVars>
+ <variable name="ACK">
+ <type>
+ <BOOL/>
+ </type>
+ </variable>
<variable name="VALID">
<type>
<BOOL/>
</type>
- </variable>
+ </variable>
<variable name="YEAR">
<type>
<UINT/>
@@ -49,7 +104,7 @@
<type>
<UINT/>
</type>
- </variable>
+ </variable>
<variable name="HOUR">
<type>
<UINT/>
@@ -67,22 +122,22 @@
</variable>
</outputVars>
<localVars>
- <variable name="pooll0">
+ <variable name="eval">
<type>
- <derived name="python_poll"/>
+ <derived name="python_eval"/>
</type>
</variable>
- <variable name="ACK">
+ <variable name="rtrig">
+ <type>
+ <derived name="R_TRIG"/>
+ </type>
+ </variable>
+ <variable name="COMPUTE">
<type>
<BOOL/>
</type>
</variable>
- <variable name="INPUT_VALUE_CODE">
- <type>
- <string/>
- </type>
- </variable>
- <variable name="CODE">
+ <variable name="DT_STR">
<type>
<string/>
</type>
@@ -91,9 +146,30 @@
</interface>
<body>
<ST>
- <xhtml:p><![CDATA[INPUT_VALUE_CODE:=CONCAT('PLCObject.MWProvider.GetRTC()'); pooll0(TRIG:=TRUE, CODE:=INPUT_VALUE_CODE, ACK => ACK, RESULT => DT_STR); VALID:=STRING_TO_BOOL(IN:=MID(IN:=DT_STR,L:=1,P:=23)); YEAR:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=4,P:=1)); MONTH:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=6)); DAY:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=9)); WDAY:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=1,P:=21)); HOUR:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=12)); MINUTE:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=15)); SECOND:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=18));]]></xhtml:p>
+ <xhtml:p><![CDATA[(* Get time from RTC *)
+eval(TRIG:=TRIG, CODE:='GetRTC()', ACK => ACK, RESULT => DT_STR);
+rtrig(CLK := ACK, Q => COMPUTE);
+IF COMPUTE OR (TRIG & ACK ) THEN
+ IF COMPUTE THEN
+ VALID:=STRING_TO_BOOL(IN:=MID(IN:=DT_STR,L:=1,P:=23));
+ YEAR:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=4,P:=1));
+ MONTH:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=6));
+ DAY:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=9));
+ WDAY:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=1,P:=21));
+ HOUR:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=12));
+ MINUTE:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=15));
+ SECOND:=STRING_TO_UINT(IN:=MID(IN:=DT_STR,L:=2,P:=18));
+ END_IF;
+ELSE
+ VALID:=FALSE;
+END_IF;
+
+]]></xhtml:p>
</ST>
</body>
+ <documentation>
+ <xhtml:p><![CDATA[Sample time from RTC on raising edge of TRIG. Outputs time as separate values and sets ACK to TRUE when output is ready. VALID is FALSE if hardware clock had a power failure and time is incorrect, TRUE otherwise.]]></xhtml:p>
+ </documentation>
</pou>
<pou name="setRTC" pouType="functionBlock">
<interface>
@@ -135,19 +211,29 @@
</variable>
</inputVars>
<outputVars>
- <variable name="RESULT">
+ <variable name="ACK">
<type>
- <string/>
+ <BOOL/>
+ </type>
+ </variable>
+ <variable name="VALID">
+ <type>
+ <BOOL/>
</type>
</variable>
</outputVars>
<localVars>
- <variable name="pooll0">
+ <variable name="eval">
<type>
- <derived name="python_poll"/>
+ <derived name="python_eval"/>
</type>
</variable>
- <variable name="ACK">
+ <variable name="rtrig">
+ <type>
+ <derived name="R_TRIG"/>
+ </type>
+ </variable>
+ <variable name="COMPUTE">
<type>
<BOOL/>
</type>
@@ -162,7 +248,7 @@
<string/>
</type>
</variable>
- <variable name="CODE">
+ <variable name="RESULT">
<type>
<string/>
</type>
@@ -171,9 +257,28 @@
</interface>
<body>
<ST>
- <xhtml:p><![CDATA[INPUT_ARGS:=CONCAT(UINT_TO_STRING(YEAR), ',', UINT_TO_STRING(MONTH), ',', UINT_TO_STRING(DAY), ',', UINT_TO_STRING(HOUR), ',', UINT_TO_STRING(MINUTE), ',', UINT_TO_STRING(SECOND)); INPUT_VALUE_CODE:=CONCAT('PLCObject.MWProvider.SetRTC(', INPUT_ARGS, ')'); pooll0(TRIG := TRIG, CODE := INPUT_VALUE_CODE, ACK => ACK, RESULT => RESULT);]]></xhtml:p>
+ <xhtml:p><![CDATA[(* Set RTC time *)
+rtrig(CLK := TRIG, Q => COMPUTE);
+IF COMPUTE THEN
+ INPUT_VALUE_CODE:=CONCAT(
+ 'SetRTC(',
+ UINT_TO_STRING(YEAR), ',',
+ UINT_TO_STRING(MONTH), ',',
+ UINT_TO_STRING(DAY), ',',
+ UINT_TO_STRING(HOUR), ',',
+ UINT_TO_STRING(MINUTE), ',',
+ UINT_TO_STRING(SECOND), ')');
+END_IF;
+eval(TRIG := TRIG, CODE := INPUT_VALUE_CODE, ACK => ACK, RESULT => RESULT);
+IF ACK THEN
+ VALID := RESULT = 'True';
+END_IF;
+]]></xhtml:p>
</ST>
</body>
+ <documentation>
+ <xhtml:p><![CDATA[Set RTC time on raising edge of TRIG]]></xhtml:p>
+ </documentation>
</pou>
</pous>
</types>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WampAuthentication.py Tue Dec 18 14:43:49 2018 +0100
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# XXX remove that crap, seriously
+
+from connectors import WAMP
+from autobahn.wamp import auth
+
+class WampSession(WAMP.WampSession):
+ def onConnect(self):
+ self.join(u"Automation", [u"wampcra"], u"smarteh")
+ print("CRA checking ...")
+
+ def onChallenge(self, challenge):
+ if challenge.method == "wampcra":
+ key = auth.derive_key("smarteh", "salt123", 100, 16)
+ return auth.compute_wcs(key, challenge.extra['challenge'])
+ else:
+ raise Exception("don't know how to handle authmethod {}".format(challenge.method))
--- a/WampOptionsEditor.py Wed Apr 11 13:06:58 2018 +0200
+++ b/WampOptionsEditor.py Tue Dec 18 14:43:49 2018 +0100
@@ -1,255 +1,419 @@
-import wx
-import sys
-
-[ID_OPTIONSWIZARDDIALOG,ID_ONCHANGE,ID_OPTIONSTYPECHOICE,ID_SUBGROUPTEXT,ID_UNITTEXT,ID_VALUECHECKBOX,ID_MINSPIN,ID_MAXSPIN,ID_PRECISIONSPIN,ID_SCADACHECKBOX,ID_OTHERTEXT,ID_DESCRIPTION,ID_STATIC] = [wx.NewId() for _init_ctrls in range(13)]
-VARIABLETYPE = ["", "Static", "Session", "Alarm"]
-
-class WampOptionsEditor(wx.Dialog):
- def _init_sizers(self):
- #self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
- self.MainSizer = wx.BoxSizer(wx.VERTICAL)
- #self.OptionsSizer = wx.FlexGridSizer(cols=2, hgap=10, rows=12, vgap=10)
- self.TypeSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.TypeSizer.Add(wx.StaticText(self,wx.ID_ANY,"Type:"), flag=wx.LEFT, border=10, proportion=1)
- self.TypeSizer.Add(self.OptionsTypeChoice, proportion=2)
- self.MainSizer.Add(self.TypeSizer, flag=wx.EXPAND|wx.RIGHT|wx.TOP, border=10)
-
- self.OnChangeSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.OnChangeSizer.Add(self.OnChangeCheckbox, flag=wx.LEFT, border=10)
- self.OnChangeSizer.Add(wx.StaticText(self, wx.ID_ANY, "On Change"), flag=wx.LEFT | wx.ALIGN_RIGHT, border=10)
- self.MainSizer.Add(self.OnChangeSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.ScadaSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.ScadaSizer.Add(self.ScadaCheckbox, flag=wx.LEFT, border=10)
- self.ScadaSizer.Add(wx.StaticText(self, wx.ID_ANY, "Scada"), flag=wx.LEFT, proportion=1, border=10)
- self.MainSizer.Add(self.ScadaSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.StaticSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.StaticSizer.Add(self.StaticCheckbox, flag=wx.LEFT, border=10)
- self.StaticSizer.Add(wx.StaticText(self, wx.ID_ANY, "Static"), flag=wx.LEFT, proportion=1, border=10)
- self.MainSizer.Add(self.StaticSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.SubgroupSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.SubgroupSizer.Add(wx.StaticText(self,wx.ID_ANY,"Subgroup:"), flag=wx.LEFT, proportion=1, border=10)
- self.SubgroupSizer.Add(self.SubgroupText, flag=wx.LEFT, border=10, proportion=2)
- self.MainSizer.Add(self.SubgroupSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.UnitSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.UnitSizer.Add(wx.StaticText(self,wx.ID_ANY,"Unit:"), flag=wx.LEFT, proportion=1, border=10)
- self.UnitSizer.Add(self.UnitText, flag=wx.LEFT, proportion=2, border=10)
- self.MainSizer.Add(self.UnitSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.ValueSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.ValueSizer.Add(self.ValueCheckbox, flag=wx.LEFT, border=10)
- self.ValueSizer.Add(wx.StaticText(self,wx.ID_ANY,"Enable min/max value"), flag=wx.LEFT, proportion=1, border=10)
- self.MainSizer.Add(self.ValueSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, proportion=2, border=10)
-
- self.minValue=wx.StaticText(self, wx.ID_ANY, "Min value:")
- self.maxValue=wx.StaticText(self, wx.ID_ANY, "Max value:")
- self.PrecisionValue = wx.StaticText(self, wx.ID_ANY, "Precision:")
-
- self.MinSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.MinSizer.Add(self.minValue, flag=wx.LEFT, border=10, proportion=1)
- self.MinSizer.Add(self.MinSpin, flag=wx.LEFT, proportion=2, border=10)
- self.MainSizer.Add(self.MinSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.MaxSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.MaxSizer.Add(self.maxValue, flag=wx.LEFT, border=10, proportion=1)
- self.MaxSizer.Add(self.MaxSpin, flag=wx.LEFT, proportion=2, border=10)
- self.MainSizer.Add(self.MaxSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.PrecisionSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.PrecisionSizer.Add(self.PrecisionValue, flag=wx.LEFT, border=10, proportion=1)
- self.PrecisionSizer.Add(self.PrecisionSpin, flag=wx.LEFT, proportion=2, border=10)
- self.MainSizer.Add(self.PrecisionSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.OtherSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.OtherSizer.Add(wx.StaticText(self, wx.ID_ANY, "Other:"), flag=wx.LEFT, border=10, proportion=1)
- self.OtherSizer.Add(self.OtherText, flag=wx.LEFT, proportion=2, border=10)
- self.MainSizer.Add(self.OtherSizer, flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
-
- self.DescriptionSizer = wx.BoxSizer(wx.VERTICAL)
- self.DescriptionSizer.Add(wx.StaticText(self, wx.ID_ANY, "Description:"), border=10)
- self.DescriptionSizer.Add(self.DescriptionText, flag=wx.EXPAND | wx.UP | wx.DOWN, proportion=1, border=10)
- self.MainSizer.Add(self.DescriptionSizer, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border=10)
-
- self.ButtonSizer.AddWindow(self.ClearButton, flag=wx.ALIGN_CENTER_HORIZONTAL)
- #self.MainSizer.AddSizer(self.OptionsSizer, 0, border=20, flag=wx.ALL)
- self.MainSizer.AddSizer(self.ButtonSizer, 0, border=10, flag=wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM)
- self.SetSizer(self.MainSizer)
- self.CenterOnParent()
-
- def _init_ctrls(self, prnt):
- wx.Dialog.__init__(self, id=ID_OPTIONSWIZARDDIALOG,
- name='OptionsWizard', parent=prnt,
- size=wx.Size(258, 520), style=wx.DEFAULT_DIALOG_STYLE,
- title='Options')
- self.OptionsTypeChoice = wx.Choice(parent=self, id=ID_OPTIONSWIZARDDIALOG,
- choices=VARIABLETYPE)
- self.Bind(wx.EVT_CHOICE, self.OnTypeChoice, self.OptionsTypeChoice)
- self.OnChangeCheckbox = wx.CheckBox(parent=self, id=ID_ONCHANGE)
- self.SubgroupText = wx.TextCtrl(parent=self, id=ID_SUBGROUPTEXT)
- self.UnitText = wx.TextCtrl(parent=self, id=ID_UNITTEXT)
- self.ValueCheckbox = wx.CheckBox(parent=self, id=ID_VALUECHECKBOX)
- self.MinSpin = wx.SpinCtrl(parent=self, id=ID_MINSPIN, style=wx.SP_VERTICAL)
- self.MaxSpin = wx.SpinCtrl(parent=self, id=ID_MAXSPIN, style=wx.SP_VERTICAL)
- self.PrecisionSpin = wx.SpinCtrl(parent=self, id=ID_PRECISIONSPIN, style=wx.SP_VERTICAL)
- #self.MinSpin.SetRange(-sys.maxsize, sys.maxsize)
- self.MinSpin.SetRange(-9999, 9999)
- #self.MaxSpin.SetRange(-sys.maxsize, sys.maxsize)
- self.MaxSpin.SetRange(-9999, 9999)
- self.ScadaCheckbox = wx.CheckBox(parent=self, id=ID_SCADACHECKBOX)
- self.StaticCheckbox = wx.CheckBox(parent=self, id=ID_SCADACHECKBOX)
- self.OtherText = wx.TextCtrl(parent=self, id=ID_OTHERTEXT)
- self.DescriptionText = wx.TextCtrl(parent=self, id=ID_DESCRIPTION, size=(-1, 100), style=wx.TE_MULTILINE | wx.SUNKEN_BORDER)
- self.ClearButton = wx.Button(self, wx.ID_CLEAR, "Clear")
- self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
- self.ValueCheckbox.Bind(wx.EVT_CHECKBOX, self.EnableValue)
- self.MinSpin.Enable(False)
- self.MaxSpin.Enable(False)
- self.OnChangeCheckbox.Enable(False)
- self.StaticCheckbox.Enable(False)
-
- self.Bind(wx.EVT_CHOICE, self.Enabler, self.OptionsTypeChoice)
- self.Bind(wx.EVT_BUTTON, self.clearOptions, self.ClearButton)
- self.Bind(wx.EVT_CHECKBOX, self.Enabler, self.ScadaCheckbox)
-
-
-
- def __init__(self, parent, opt, desc):
- self.TypeSelected = 0
- self.value = ""
- self.Description = ""
- self.OnChange = False
- self._init_ctrls(parent)
- self._init_sizers()
- self.SetOptions(opt, desc)
- self.GetOptions()
-
- def Enabler(self, event):
- if self.OptionsTypeChoice.GetSelection() in [1,3]:
- self.OnChangeCheckbox.Enable(True)
- else:
- self.OnChangeCheckbox.Enable(False)
- if self.OptionsTypeChoice.GetSelection() == 3 and self.ScadaCheckbox.GetValue():
- self.StaticCheckbox.Enable(True)
- else:
- self.StaticCheckbox.Enable(False)
-
-
-
- def clearOptions(self, event):
- """Zbrisi vsebino"""
- self.OptionsTypeChoice.SetSelection(0)
- self.SubgroupText.SetLabel("")
- self.UnitText.SetLabel("")
- self.MinSpin.SetValue(0)
- self.MaxSpin.SetValue(0)
- self.ValueCheckbox.SetValue(False)
- self.ScadaCheckbox.SetValue(False)
- self.StaticCheckbox.SetValue(False)
- self.OtherText.SetLabel("")
- self.MinSpin.Enable(False)
- self.MaxSpin.Enable(False)
- self.StaticCheckbox.Enable(False)
- self.PrecisionSpin.SetValue(0)
- self.OnChangeCheckbox.SetValue(False)
- self.DescriptionText.SetLabel("")
-
- def OnTypeChoice(self, event):
- self.selected = event.GetSelection()
-
- def EnableValue(self, event):
- self.MinSpin.Enable(self.ValueCheckbox.GetValue())
- self.MaxSpin.Enable(self.ValueCheckbox.GetValue())
-
- # def MinChange(self,event):
- # self.minValue.SetLabel("Min value: " + str(self.MinSpin.GetValue()))
- #
- # def MaxChange(self,event):
- # self.maxValue.SetLabel("Max value: " + str(self.MaxSpin.GetValue()))
-
- def SetOptions(self, opt, desc):
- opt1 = opt[0]
- opt2 = opt[1]
- optionsTemp = opt1.split(" ")
- options = []
- for el in optionsTemp:
- options.append(el.split("="))
- self.clearOptions(None)
- # self.ScadaCheckbox.SetValue(False)
- # self.StaticCheckbox.Enable(False)
- # self.StaticCheckbox.SetValue(False)
- for el in options:
- if len(el) == 1:
- if el[0] == "":
- self.OptionsTypeChoice.SetSelection(0)
- elif el[0] == "Static":
- self.OptionsTypeChoice.SetSelection(1)
- elif el[0] == "Session":
- self.OptionsTypeChoice.SetSelection(2)
- elif el[0] == "Alarm":
- self.OptionsTypeChoice.SetSelection(3)
- if el[0] == "scada":
- self.ScadaCheckbox.SetValue(True)
- if el[0] == "static":
- self.StaticCheckbox.Enable(True)
- self.StaticCheckbox.SetValue(True)
- else:
- if el[0] == "subgroup":
- self.SubgroupText.SetLabel(el[1])
- elif el[0] == "unit":
- self.UnitText.SetLabel(el[1])
- elif el[0] == "min":
- self.ValueCheckbox.SetValue(True)
- self.MinSpin.SetValue(int(el[1]))
- self.MinSpin.Enable(True)
- elif el[0] == "max":
- self.ValueCheckbox.SetValue(True)
- self.MaxSpin.SetValue(int(el[1]))
- self.MaxSpin.Enable(True)
- elif el[0] == "other":
- self.OtherText.SetLabel(el[1])
- elif el[0] == "precision":
- self.PrecisionSpin.SetValue(int(el[1]))
- if len(opt2)>0:
- self.OnChangeCheckbox.Enable(True)
- self.OnChangeCheckbox.SetValue(True)
- if self.OptionsTypeChoice.GetSelection() == 3 and self.ScadaCheckbox.GetValue():
- self.StaticCheckbox.Enable(True)
- self.DescriptionText.SetLabel(desc)
-
-
- def GetOptions(self):
- self.TypeSelected = self.OptionsTypeChoice.GetSelection()
- if self.TypeSelected<0:
- self.TypeSelected = 0
- options = VARIABLETYPE[self.TypeSelected]
- if self.ScadaCheckbox.GetValue():
- options += " scada"
- if self.StaticCheckbox.GetValue():
- options += " static"
- if self.SubgroupText.GetLineText(0) != "":
- options += " subgroup=" + self.SubgroupText.GetLineText(0)
- if self.UnitText.GetLineText(0) != "":
- options += " unit=" + self.UnitText.GetLineText(0)
- if self.MinSpin.IsEnabled():
- options += " min=" + str(self.MinSpin.GetValue())
- options += " max=" + str(self.MaxSpin.GetValue())
- if self.PrecisionSpin.GetValue() != 0:
- options += " precision=" + str(self.PrecisionSpin.GetValue())
- if self.OtherText.GetLineText(0) != "":
- options += " other=" + self.OtherText.GetLineText(0)
- if self.OnChangeCheckbox.GetValue():
- self.OnChange = True
- else:
- self.OnChange = False
- if VARIABLETYPE[self.TypeSelected] == "Alarm":
- self.value = "Alarm"
- elif VARIABLETYPE[self.TypeSelected] == "Static":
- self.value = "StoredValue"
- else:
- self.value = ""
- self.OnChange = True
- self.Description = self.DescriptionText.GetValue()
- return options, self.OnChange,self.value, self.Description
\ No newline at end of file
+from __future__ import absolute_import
+import wx
+import wx.grid
+import controls
+
+[ID_OPTIONSWIZARDDIALOG,ID_ONCHANGE,ID_OPTIONSTYPECHOICE,ID_SUBGROUPTEXT,ID_UNITTEXT,ID_VALUECHECKBOX,ID_MINSPIN,ID_MAXSPIN,ID_PRECISIONSPIN, ID_INITIALSPIN,ID_SCADACHECKBOX,ID_OTHERTEXT,ID_DESCRIPTION,ID_STATIC] = [wx.NewId() for _init_ctrls in range(14)]
+VARIABLETYPE = ["None", "Static", "Session", "Alarm"]
+
+class WampOptionsEditor(wx.Dialog):
+ def _init_sizers(self):
+ self.MainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.PropertySizer = wx.FlexGridSizer(cols=2, hgap=10, rows=13, vgap=10)
+ self.PropertySizer.AddWindow(wx.StaticText(self,wx.ID_ANY,_("Type:")), flag=wx.ALIGN_CENTER_VERTICAL | wx.GROW | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.OptionsTypeChoice, 1, flag= wx.EXPAND)
+
+ self.PropertySizer.AddWindow(self.OnChangeCheckbox, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(wx.StaticText(self, wx.ID_ANY, _("On Change")), 1, flag=wx.GROW | wx.EXPAND)
+
+ self.PropertySizer.AddWindow(self.ScadaCheckbox, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(wx.StaticText(self, wx.ID_ANY, _("Scada")), 1, flag=wx.GROW | wx.EXPAND)
+
+ self.PropertySizer.AddWindow(self.StaticCheckbox, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(wx.StaticText(self, wx.ID_ANY, _("Static")), 1, flag=wx.GROW | wx.EXPAND)
+
+ self.PropertySizer.AddWindow(wx.StaticText(self,wx.ID_ANY, _("Subgroup:")), flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.SubgroupText, 1, flag=wx.GROW | wx.EXPAND)
+
+ self.PropertySizer.AddWindow(wx.StaticText(self,wx.ID_ANY, _("Unit:")), flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.UnitText, 1, flag=wx.GROW | wx.EXPAND)
+
+ self.PropertySizer.AddWindow(self.ValueCheckbox, flag=wx.GROW | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(wx.StaticText(self,wx.ID_ANY, _("Enable min/max value")), flag=wx.ALIGN_CENTER_VERTICAL)
+
+ self.minValue=wx.StaticText(self, wx.ID_ANY, _("Min value:"))
+ self.maxValue=wx.StaticText(self, wx.ID_ANY, _("Max value:"))
+ self.PrecisionValue = wx.StaticText(self, wx.ID_ANY, _("Precision:"))
+ self.InitialValue = wx.StaticText(self, wx.ID_ANY, _("Initial:"))
+
+ self.PropertySizer.AddWindow(self.minValue, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.MinSpin, flag=wx.GROW)
+
+ self.PropertySizer.AddWindow(self.maxValue, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.MaxSpin, flag=wx.GROW)
+
+ self.PropertySizer.AddWindow(self.PrecisionValue, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.PrecisionSpin, flag=wx.GROW)
+
+ self.PropertySizer.AddWindow(wx.StaticText(self, wx.ID_ANY, _("Other:")), flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.OtherText, flag=wx.GROW)
+
+ self.PropertySizer.AddWindow(self.InitialValue, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.InitialText, flag=wx.GROW)
+
+ self.PropertySizer.AddWindow(wx.StaticText(self, wx.ID_ANY, _("Description:")), flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
+ self.PropertySizer.AddWindow(self.DescriptionText, flag=wx.GROW)
+
+ self.PropertySizer.AddGrowableCol(1, 1)
+ self.MainSizer.AddSizer(self.PropertySizer, flag=wx.GROW | wx.UP | wx.RIGHT, border=15)
+ self.ButtonSizer.AddWindow(self.ClearButton)
+ self.MainSizer.AddSizer(self.ButtonSizer,
+ flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 10)
+
+ self.SetSizer(self.MainSizer)
+ self.Fit()
+ self.CenterOnScreen()
+
+ def _init_ctrls(self, prnt, opt):
+ wx.Dialog.__init__(self, id=ID_OPTIONSWIZARDDIALOG,
+ name='OptionsWizard', parent=prnt,
+ size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE,
+ title=_('Options'))
+ self.OptionsTypeChoice = wx.Choice(parent=self, id=ID_OPTIONSWIZARDDIALOG,
+ choices=VARIABLETYPE)
+ self.Bind(wx.EVT_CHOICE, self.OnTypeChoice, self.OptionsTypeChoice)
+ self.OnChangeCheckbox = wx.CheckBox(parent=self, id=ID_ONCHANGE)
+ self.SubgroupText = wx.TextCtrl(parent=self, id=ID_SUBGROUPTEXT)
+ self.UnitText = wx.TextCtrl(parent=self, id=ID_UNITTEXT)
+ self.ValueCheckbox = wx.CheckBox(parent=self, id=ID_VALUECHECKBOX)
+ self.MinSpin = wx.SpinCtrl(parent=self, id=ID_MINSPIN, style=wx.SP_VERTICAL)
+ self.MaxSpin = wx.SpinCtrl(parent=self, id=ID_MAXSPIN, style=wx.SP_VERTICAL)
+ self.PrecisionSpin = wx.SpinCtrl(parent=self, id=ID_PRECISIONSPIN, style=wx.SP_VERTICAL)
+ self.InitialText = wx.TextCtrl(parent=self, id=ID_INITIALSPIN)
+ self.MinSpin.SetRange(-1000000, 1000000)
+ self.MaxSpin.SetRange(-1000000, 1000000)
+ self.ScadaCheckbox = wx.CheckBox(parent=self, id=ID_SCADACHECKBOX)
+ self.StaticCheckbox = wx.CheckBox(parent=self, id=ID_STATIC)
+ self.OtherText = wx.TextCtrl(parent=self, id=ID_OTHERTEXT)
+ self.DescriptionText = wx.TextCtrl(parent=self, id=ID_DESCRIPTION, size=(-1, 100), style=wx.TE_MULTILINE | wx.SUNKEN_BORDER)
+ self.ClearButton = wx.Button(self, wx.ID_CLEAR, _("Clear"))
+ self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
+ self.ValueCheckbox.Bind(wx.EVT_CHECKBOX, self.EnableValue)
+ self.OnChangeCheckbox.Enable(False)
+ self.OtherText.Enable(False)
+ self.UnitText.Enable(False)
+ self.ScadaCheckbox.Enable(False)
+ self.SubgroupText.Enable(False)
+ self.ValueCheckbox.Enable(False)
+ self.MinSpin.Enable(False)
+ self.MaxSpin.Enable(False)
+ self.PrecisionSpin.Enable(False)
+ self.InitialText.Enable(False)
+ self.DescriptionText.Enable(False)
+ self.StaticCheckbox.Enable(False)
+
+ self.Bind(wx.EVT_CHOICE, self.Enabler, self.OptionsTypeChoice)
+ self.Bind(wx.EVT_BUTTON, self.clearOptions, self.ClearButton)
+ self.Bind(wx.EVT_CHECKBOX, self.Enabler, self.ScadaCheckbox)
+
+
+
+ def __init__(self, parent, opt, desc):
+ self.TypeSelected = 0
+ self.options = opt
+ self.value = ""
+ self.Description = ""
+ self.OnChange = False
+ self._init_ctrls(parent, opt)
+ self._init_sizers()
+ self.SetOptions(opt, desc)
+ self.GetOptions()
+ self.Enabler(None)
+
+
+ def Enabler(self, event):
+ if self.OptionsTypeChoice.GetSelection() == 0:
+ self.clearOptions(event)
+ elif self.OptionsTypeChoice.GetSelection() in [1,3]:
+ self.ScadaCheckbox.Enable(True)
+ self.OtherText.Enable(True)
+ self.SubgroupText.Enable(True)
+ self.UnitText.Enable(True)
+ self.OnChangeCheckbox.Enable(True)
+ self.ValueCheckbox.Enable(True)
+ self.PrecisionSpin.Enable(True)
+ self.InitialText.Enable(True)
+ self.DescriptionText.Enable(True)
+ else:
+ self.ScadaCheckbox.Enable(True)
+ self.OtherText.Enable(True)
+ self.SubgroupText.Enable(True)
+ self.UnitText.Enable(True)
+ self.OnChangeCheckbox.SetValue(False)
+ self.OnChangeCheckbox.Enable(False)
+ self.ValueCheckbox.Enable(True)
+ self.PrecisionSpin.Enable(True)
+ self.InitialText.Enable(True)
+ self.DescriptionText.Enable(True)
+
+ if self.OptionsTypeChoice.GetSelection() == 3 and self.ScadaCheckbox.GetValue():
+ self.StaticCheckbox.Enable(True)
+ self.OnChangeCheckbox.SetValue(True)
+ else:
+
+ self.StaticCheckbox.SetValue(False)
+ self.StaticCheckbox.Enable(False)
+
+
+
+ def clearOptions(self, event):
+ """Zbrisi vsebino"""
+ self.OptionsTypeChoice.SetSelection(0)
+ self.SubgroupText.SetValue("")
+ self.UnitText.SetValue("")
+ self.MinSpin.SetValue(0)
+ self.MaxSpin.SetValue(0)
+ self.ValueCheckbox.SetValue(False)
+ self.ScadaCheckbox.SetValue(False)
+ self.StaticCheckbox.SetValue(False)
+ self.OtherText.SetValue("")
+ self.MinSpin.Enable(False)
+ self.MaxSpin.Enable(False)
+ self.StaticCheckbox.Enable(False)
+ self.PrecisionSpin.SetValue(0)
+ self.InitialText.SetValue("")
+ self.OnChangeCheckbox.SetValue(False)
+ self.DescriptionText.SetValue("")
+ self.OnChangeCheckbox.Enable(False)
+ self.OtherText.Enable(False)
+ self.SubgroupText.Enable(False)
+ self.UnitText.Enable(False)
+ self.ScadaCheckbox.Enable(False)
+ self.ValueCheckbox.Enable(False)
+ self.MinSpin.Enable(False)
+ self.MaxSpin.Enable(False)
+ self.PrecisionSpin.Enable(False)
+ self.InitialText.Enable(False)
+ self.DescriptionText.Enable(False)
+ self.StaticCheckbox.Enable(False)
+
+ def OnTypeChoice(self, event):
+ self.selected = event.GetSelection()
+
+ def EnableValue(self, event):
+ self.MinSpin.Enable(self.ValueCheckbox.GetValue())
+ self.MaxSpin.Enable(self.ValueCheckbox.GetValue())
+
+ def SetOptions(self, opt, desc):
+ opt1 = opt[0]
+ opt2 = opt[1]
+ opt3 = opt[2]
+ optionsTemp = opt1.split(" ")
+ options = []
+ for el in optionsTemp:
+ options.append(el.split("="))
+ for el in options:
+ if len(el) == 1:
+ if el[0] == "":
+ self.OptionsTypeChoice.SetSelection(0)
+ elif el[0] == "Static":
+ self.OptionsTypeChoice.SetSelection(1)
+ elif el[0] == "Session":
+ self.OptionsTypeChoice.SetSelection(2)
+ elif el[0] == "Alarm":
+ self.OptionsTypeChoice.SetSelection(3)
+ if el[0] == "scada":
+ self.ScadaCheckbox.SetValue(True)
+ if el[0] == "static":
+ self.StaticCheckbox.Enable(True)
+ self.StaticCheckbox.SetValue(True)
+ else:
+ if el[0] == "subgroup":
+ self.SubgroupText.SetValue(el[1])
+ elif el[0] == "unit":
+ self.UnitText.SetValue(el[1])
+ elif el[0] == "min":
+ self.ValueCheckbox.SetValue(True)
+ self.MinSpin.SetValue(int(el[1]))
+ self.MinSpin.Enable(True)
+ elif el[0] == "max":
+ self.ValueCheckbox.SetValue(True)
+ self.MaxSpin.SetValue(int(el[1]))
+ self.MaxSpin.Enable(True)
+ elif el[0] == "other":
+ self.OtherText.SetValue(el[1])
+ elif el[0] == "precision":
+ self.PrecisionSpin.SetValue(int(el[1]))
+ if len(opt2)>0:
+ self.OnChangeCheckbox.Enable(True)
+ self.OnChangeCheckbox.SetValue(True)
+ if self.OptionsTypeChoice.GetSelection() == 3 and self.ScadaCheckbox.GetValue():
+ self.StaticCheckbox.Enable(True)
+ if opt3 != "":
+ self.InitialText.SetValue(opt3)
+ self.DescriptionText.SetValue(desc)
+
+
+ def GetOptions(self):
+ self.TypeSelected = self.OptionsTypeChoice.GetSelection()
+ if self.TypeSelected<0:
+ self.TypeSelected = 0
+ options = VARIABLETYPE[self.TypeSelected]
+ if options == "None":
+ options = ""
+ if self.ScadaCheckbox.GetValue():
+ options += " scada"
+ if self.StaticCheckbox.GetValue():
+ options += " static"
+ if self.SubgroupText.GetLineText(0) != "":
+ options += " subgroup=" + self.SubgroupText.GetLineText(0)
+ if self.UnitText.GetLineText(0) != "":
+ options += " unit=" + self.UnitText.GetLineText(0)
+ if self.MinSpin.IsEnabled():
+ options += " min=" + str(self.MinSpin.GetValue())
+ options += " max=" + str(self.MaxSpin.GetValue())
+ if self.PrecisionSpin.GetValue() != 0:
+ options += " precision=" + str(self.PrecisionSpin.GetValue())
+ if self.OtherText.GetLineText(0) != "":
+ options += " other=" + self.OtherText.GetLineText(0)
+ if self.OnChangeCheckbox.GetValue():
+ self.OnChange = True
+ else:
+ self.OnChange = False
+ if VARIABLETYPE[self.TypeSelected] == "Alarm":
+ self.value = "Alarm"
+ elif VARIABLETYPE[self.TypeSelected] == "Static":
+ self.value = "StoredValue"
+ else:
+ self.value = ""
+ self.OnChange = True
+ self.Description = self.DescriptionText.GetValue()
+ self.Initial = self.InitialText.GetValue()
+ return options, self.OnChange,self.value, self.Description, self.Initial
+
+
+class WampOptionsCellControl(wx.PyControl):
+ '''
+ Custom cell editor control with a text box and a button that launches
+ the WampOptionsEditor.
+ '''
+
+ def __init__(self, parent, table, row):
+ wx.Control.__init__(self, parent, row)
+
+ main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
+ main_sizer.AddGrowableCol(0)
+ main_sizer.AddGrowableRow(0)
+
+ self.parent = parent
+
+ # create location text control
+ self.Options = wx.TextCtrl(self, size=wx.Size(0, -1),
+ style=wx.TE_PROCESS_ENTER)
+ self.Options.Bind(wx.EVT_KEY_DOWN, self.OnDurationChar)
+ main_sizer.AddWindow(self.Options, flag=wx.GROW)
+
+ # create browse button
+ self.EditButton = wx.Button(self, label='...', size=wx.Size(30, -1))
+ self.Bind(wx.EVT_BUTTON, self.OnEditButtonClick, self.EditButton)
+ main_sizer.AddWindow(self.EditButton, flag=wx.GROW)
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+
+ self.SetSizer(main_sizer)
+
+ self.Default = None
+ self.table = table
+ self.row = row
+
+ def OnDurationChar(self, event):
+ keycode = event.GetKeyCode()
+ if keycode in [wx.WXK_RETURN, wx.WXK_TAB]:
+ self.Parent.Parent.ProcessEvent(event)
+ elif keycode == wx.WXK_ESCAPE:
+ self.Duration.SetValue(self.Default)
+ self.Parent.Parent.CloseEditControl()
+ else:
+ event.Skip()
+
+ def SetValue(self, value):
+ self.Default = value
+ self.Options.SetValue(value)
+
+ def GetValue(self):
+ return self.Options.GetValue()
+
+ def OnSize(self, event):
+ self.Layout()
+
+ def OnEditButtonClick(self, event):
+ # pop up the Duration Editor dialog
+ options = [self.GetValue(), self.table.GetValueByName(self.row, _("OnChange")), self.table.GetValueByName(self.row, "Initial")]
+ desc = self.table.GetValueByName(self.row, _("Description"))
+ dialog = WampOptionsEditor(self.parent, options, desc)
+ answer = dialog.ShowModal()
+ opt, OnChange, value, description, initial = dialog.GetOptions()
+ if answer == wx.ID_OK:
+ self.SetValue(opt)
+ if OnChange:
+ self.table.SetValueByName(self.row, _("OnChange"), value)
+ else:
+ self.table.SetValueByName(self.row, _("OnChange"), "")
+ self.table.SetValueByName(self.row, _("Description"), description)
+ self.table.SetValueByName(self.row, _("Initial"), str(initial))
+
+ dialog.Destroy()
+
+ self.Options.SetFocus()
+
+ def OnChar(self, event):
+ keycode = event.GetKeyCode()
+ if keycode in [wx.WXK_RETURN]:
+ self.Parent.Parent.ProcessEvent(event)
+ elif keycode == wx.WXK_ESCAPE:
+ self.Options.SetValue(self.Default)
+ self.Parent.Parent.CloseEditControl()
+ else:
+ event.Skip()
+
+ def SetFocus(self):
+ self.Options.SetFocus()
+
+
+class WampOptionsCellEditor(wx.grid.PyGridCellEditor):
+ '''
+ Grid cell editor that uses DurationCellControl to display an edit button.
+ '''
+
+ def __init__(self, table, row, col):
+ wx.grid.PyGridCellEditor.__init__(self)
+
+ self.table = table
+ self.colname = self.table.GetColLabelValue(col, False)
+ self.row = row
+
+ def __del__(self):
+ self.CellControl = None
+
+ def Create(self, parent, id, evt_handler):
+ self.CellControl = WampOptionsCellControl(parent, self.table, self.row)
+ self.SetControl(self.CellControl)
+ if evt_handler:
+ self.CellControl.PushEventHandler(evt_handler)
+
+ def BeginEdit(self, row, col, grid):
+ self.CellControl.Enable()
+ self.CellControl.SetValue(self.table.GetValueByName(self.row, self.colname))
+ self.CellControl.SetFocus()
+
+ def EndEditInternal(self, row, col, grid, old_duration):
+ duration = self.CellControl.GetValue()
+ changed = duration != old_duration
+ if changed:
+ self.table.SetValueByName(row, self.colname, duration)
+ self.CellControl.Disable()
+ return changed
+
+ if wx.VERSION >= (3, 0, 0):
+ def EndEdit(self, row, col, grid, oldval):
+ return self.EndEditInternal(row, col, grid, oldval)
+ else:
+ def EndEdit(self, row, col, grid):
+ oldval = self.table.GetValueByName(row, self.colname)
+ return self.EndEditInternal(row, col, grid, oldval)
+
+ def SetSize(self, rect):
+ self.CellControl.SetDimensions(rect.x + 1, rect.y,
+ rect.width, rect.height,
+ wx.SIZE_ALLOW_MINUS_ONE)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WxGladeEditor.py Tue Dec 18 14:43:49 2018 +0100
@@ -0,0 +1,10 @@
+from __future__ import absolute_import
+from editors.CodeFileEditor import CodeFileEditor
+from py_ext.PythonEditor import PythonCodeEditor
+
+
+class WxGladeEditor(CodeFileEditor):
+
+ CONFNODEEDITOR_TABS = [
+ (_("Python code"), "_create_CodePanel")]
+ CODE_EDITOR = PythonCodeEditor
\ No newline at end of file