ELV IPIO88 In/Out Interface plugin

Questions and comments specific to a particular plugin should go here.

ELV IPIO88 In/Out Interface plugin

Postby ottisaft » Thu Jun 01, 2017 1:19 pm

Hi,

this is my first post here and first of all I would like to say that EG is absolutely fantastic. I use it for serveral years now and it's my multi-tool knife for so many automation projects! Many thanks to everybody who is involved in the continuous improvement of EG.

For a home automation project I would like to use the ELV IPIO-88 In/Out Interface. https://www.elv.de/ip-i-o-interface-ipio-88-komplettbausatz.html.

There was no plugin avialable, therefore - with the help of the tutorial - I created my own. I have to say that I'm not experienced in python or scripting at all. The plugin is very basic (see att).

Now I have two issue I couldn't figure out.

1.) I would like to add a checkbox in the config panel to have the possiblity to suppress events during start of the plugin and a field to set the refresh rate which is currently fixed.

2.) I would like to start multiple instances (one for each device), That is not possible in the moment.

Thanks in advance for your help!

Ottisaft
Attachments
__init__.zip
(2.31 KiB) Downloaded 24 times
User avatar
ottisaft
 
Posts: 3
Joined: Fri May 19, 2017 11:00 am
Location: Germany

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Thu Jun 01, 2017 1:47 pm

No worries m8 this I can help you with. Later today I can check out what ya have and make some suggestions. And point ya in the right direction. I have authored a neet little Python script I can send to ya later today. But it will basically set up the basics of a plugin for ya with all the proper bits in place and will also add threading and things of that nature. It is ment to be used as a outline for your plugin. It doesn't add everything. But it adds enough to give you the layout and also provides descriptions of how to use the different pieces. I think you will find this helpful.
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Sat Jun 03, 2017 7:19 am

if you copy and paste the code below into a python script and run it it will bring up a little program i made. it does some basic layout stuff for a plugin but it will give you the general idea as to what is going on.


Code: Select all
import wx
from comtypes import GUID


REGISTER_PLUGIN = '''# -*- coding: utf-8 -*-
#
# This file is part of EventGhost.
# Copyright © 2005-2016 EventGhost Project <http://www.eventghost.org/>
#
# EventGhost is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# EventGhost is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with EventGhost. If not, see <http://www.gnu.org/licenses/>.

import eg

eg.RegisterPlugin(
{RegisterPlugin}
)


{ThreadClass}


class Text:
    # add variables with string that you want to be able to have translated
    # using the language editor in here
    {ActionText}


class {PluginName}(eg.PluginBase):
    text = Text

    # you want to add any variables that can be access from anywhere inside of
    # your plugin here
    def __init__(self):
        {AddAction}
        {ThreadInit}
   
    # you will want to add any startup parameters and also run any startup code
    # here
    def __start__(self, *args):
        {ThreadStart}
   
    # this gets called when eg is being closed and you can run code when that
    # happens
    def __close__(self):
        pass
       
    # this gets called as well when EG closes but it also gets called when a
    # plugin gets disabled. This is where you will do things like close any
    # open sockets
    def __stop__(self):
        {ThreadStop}
       
    # You will replace the code in this method if you want to make a plugin
    # configuration dialog.
    def Configure(self, *args):
        eg.PluginBase.Configure(self, *args)

   
    # The next 2 are pretty self explanatory
    def OnComputerResume(self):
        pass
   
    def OnComputerSuspend(self):
        pass
   
    # This gets called when a plugin gets deleted from the tree. so here if
    # you use eg.PersistantData to store any data. that data needs to be
    # deleted when the plugin gets removed. this is where that gets done.
    def OnDelete(self):
        pass

{ActionClass}
'''

KIND_CHOICES = [
    'other',
    'remote',
    'external',
    'program'
]


add_action = 'self.AddAction(%s)'

action_text = '''
    class %s:
        name = %r
        description = 'Action %s'
'''

action_class = '''

class %s(eg.ActionBase):

    # this code gets executed when the action gets run
    def __call__(self, *args):
        pass
       
    # this is where you would put the code for an action configuration dialog
    def Configure(self, *args):
        text = self.text
        panel = eg.ConfigPanel()
       
        while panel.Affirmed():
            panel.SetResult()
'''


thread_stop = 'self.plugin_thread.stop()'
thread_init = 'self.plugin_thread = ThreadClass(self)'
thread_start = 'self.plugin_thread.start(*args)'
thread_class = '''
import threading # NOQA


class ThreadClass(object):
    def __init__(self, plugin):
        self.event = threading.Event()
        self.plugin = plugin
        self.args = None
        self.thread = None
       
    def start(self, *args):
        if self.thread is None:
            self.args = args
            self.thread = threading.Thread(name=__name__, target=self.run)
           
    def run(self):
        self.event.clear()
        while not self.event.isSet():
            # do your code here
            # if you need to wait use
            # self.event.wait(seconds)
            pass
           
        self.thread = None
       
    def stop(self):
        if self.thread is not None:
            self.event.set()
            self.thread.join(3)
'''


def PrettyPythonPrint(attrName, attrValue):
    types = (unicode, str)

    line = '    %s=' % attrName
    multiLine = len(line + repr(attrValue)) > 76

    if type(attrValue) in types and multiLine:
        newAttrValue = ()
        while attrValue:
            jump = min([len(attrValue), 67])
            value = attrValue[:jump]
            if '\n' in value:
                jump = value.find('\n') + 1
            elif value.endswith('.') or value.endswith(' '):
                pass
            elif ' ' in value:
                jump = value.rfind(' ') + 1

            newAttrValue += (attrValue[:jump],)
            attrValue = attrValue[jump:]
        attrValue = newAttrValue

        line += '(\n'
        for item in attrValue:
            line += '        %r\n' % item
        line = line[:-2] + '\n' + '    ),\n'
    else:
        line += '%r,\n' % attrValue

    return line


class StringFloatRange(str):

    def __init__(self, x, y, jump):
        str.__init__(x)

    def __new__(cls, x, y, jump):
        if jump < 0:
            while x > y:
                yield str.__new__(cls, format(x, '.1f'))
                x += jump
        else:
            while x < y:
                yield str.__new__(cls, format(x, '.1f'))
                x += jump

VERSION_CHOICES = list(item for item in StringFloatRange(0.1, 10.0, 0.1))


def EqualizeWidths(*ctrls):
    maxWidth = max((ctrl.GetBestSize()[0] for ctrl in ctrls))
    for ctrl in ctrls:
        ctrl.SetMinSize((maxWidth, -1))


class Frame(wx.Frame):

    ctrl = None
    frame = None

    def __init__(self):

        width = 80 * 6

        guid = str(GUID.create_new())

        wx.Frame.__init__(
            self,
            eg.document.frame,
            size=((width + 50) * 2, 850),
            title='Register Plugin Generator'
        )

        nameSt = wx.StaticText(self, -1, 'Name:')
        nameCtrl = wx.TextCtrl(self, -1, '')
        authorSt = wx.StaticText(self, -1, 'Author:')
        authorCtrl = wx.TextCtrl(self, -1, '')
        versionSt = wx.StaticText(self, -1, 'Version:')
        versionCtrl = wx.Choice(self, -1, choices=VERSION_CHOICES)
        verAlphaSt = wx.StaticText(self, -1, 'Alpha:')
        verAlphaCtrl = wx.CheckBox(self, -1, '', name='a')
        verBetaSt = wx.StaticText(self, -1, 'Beta:')
        verBetaCtrl = wx.CheckBox(self, -1, '', name='b')
        descSt = wx.StaticText(self, -1, 'Description')
        descCtrl = wx.TextCtrl(self, -1, '', style=wx.TE_MULTILINE, size=(width, 200))
        helpSt = wx.StaticText(self, -1, 'Help')
        helpCtrl = wx.TextCtrl(self, -1, '', style=wx.TE_MULTILINE, size=(width, 200))
        urlSt = wx.StaticText(self, -1, 'URL:')
        urlCtrl = wx.TextCtrl(self, -1, '')
        hardwareSt = wx.StaticText(self, -1, 'Hardware Id\'s')
        hardwareCtrl = wx.TextCtrl(self, -1, '', style=wx.TE_MULTILINE, size=(width, 200))
        kindSt = wx.StaticText(self, -1, 'Kind:')
        kindCtrl = wx.Choice(self, -1, choices=KIND_CHOICES)
        guidSt = wx.StaticText(self, -1, 'GUID:')
        guidCtrl = wx.TextCtrl(self, -1, guid, style=wx.TE_READONLY, size=(len(guid) * 7, 20))
        macroSt = wx.StaticText(self, -1, 'Create Macros:')
        macroCtrl = wx.CheckBox(self, -1, '')
        multiloadSt = wx.StaticText(self, -1, 'Can Multiload:')
        multiloadCtrl = wx.CheckBox(self, -1, '')

        iconSt = wx.StaticText(self, -1, 'Icon')
        iconCtrl = wx.TextCtrl(self, -1, 'None', style=wx.TE_MULTILINE, size=(width, 164))
        iconBaseSt = wx.StaticText(self, -1, 'Encode Icon:')
        iconBaseCtrl = wx.CheckBox(self, -1, '')

        action_st = wx.StaticText(self, -1, 'Action Names (comma separated):')
        action_ctrl = wx.TextCtrl(self, -1, '')

        thread_st = wx.StaticText(self, -1, 'Add threading class: ')
        thread_ctrl = wx.CheckBox(self)

        EqualizeWidths(
            verAlphaSt,
            verBetaSt
        )

        EqualizeWidths(
            nameSt,
            authorSt,
            versionSt,
            descSt,
            helpSt,
            urlSt,
            hardwareSt,
            kindSt,
            guidSt,
            macroSt,
            multiloadSt,
            iconSt,
            iconBaseSt
        )

        kindCtrl.SetSelection(0)
        versionCtrl.SetSelection(0)
        verAlphaCtrl.SetValue(False)
        verBetaCtrl.SetValue(False)
        macroCtrl.SetValue(True)
        multiloadCtrl.SetValue(False)

        def OnChangeVer(evt):
            char = evt.GetEventObject().GetName()

            if not evt.GetInt():
                char = ''

            if char == 'a':
                verBetaCtrl.SetValue(False)
            else:
                verAlphaCtrl.SetValue(False)

            verChoices = list(ver + char for ver in VERSION_CHOICES[:])
            value = versionCtrl.GetSelection()
            versionCtrl.Clear()
            versionCtrl.AppendItems(verChoices)
            versionCtrl.SetSelection(value)
            evt.Skip()

        verAlphaCtrl.Bind(wx.EVT_CHECKBOX, OnChangeVer)
        verBetaCtrl.Bind(wx.EVT_CHECKBOX, OnChangeVer)

        verTypeSizer = wx.BoxSizer(wx.HORIZONTAL)
        verTypeSizer.Add(verAlphaSt, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 20)
        verTypeSizer.Add(verAlphaCtrl, 0, wx.EXPAND)
        verTypeSizer.Add(verBetaSt, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 20)
        verTypeSizer.Add(verBetaCtrl, 0, wx.EXPAND)

        iconBaseSizer = wx.BoxSizer(wx.HORIZONTAL)
        iconBaseSizer.Add(iconBaseSt, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 20)
        iconBaseSizer.Add(iconBaseCtrl, 0, wx.EXPAND)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        leftSizer = wx.BoxSizer(wx.VERTICAL)
        middleSizer = wx.BoxSizer(wx.VERTICAL)
        rightSizer = wx.BoxSizer(wx.VERTICAL)
        leftMultiSizer = wx.BoxSizer(wx.VERTICAL)
        rightMultiSizer = wx.BoxSizer(wx.VERTICAL)

        def OnView(evt):
            text = [
                ('name', unicode(nameCtrl.GetValue())),
                ('author', unicode(authorCtrl.GetValue())),
                ('version', unicode(versionCtrl.GetStringSelection())),
                ('description', unicode(descCtrl.GetValue())),
                ('kind', unicode(kindCtrl.GetStringSelection())),
                ('url', unicode(urlCtrl.GetValue())),
                ('help', unicode(helpCtrl.GetValue())),
                ('canMultiLoad',multiloadCtrl.GetValue()),
                ('createMacrosOnAdd', macroCtrl.GetValue()),
                ('guid', unicode(guidCtrl.GetValue())),
                ('hardwareId', unicode(hardwareCtrl.GetValue())),
                (
                    'icon',
                    unicode(iconCtrl.GetValue())
                    if iconCtrl.GetValue() != 'None' else None
                )
            ]

            actions = action_ctrl.GetValue()
            if actions.strip():
                addActions = ''
                actionText = ''
                actionClass = ''

                for action in actions.split(','):
                    action = action.title().strip()
                    class_name = action.replace('-', '_').replace(' ', '_')
                    addActions += add_action % class_name + '\n        '
                    actionText += action_text % (class_name, action, action) + '\n    '
                    actionClass += action_class % class_name
            else:
                addActions = 'pass'
                actionText = 'pass'
                actionClass = ''

            if thread_ctrl.GetValue():
                threadClass = thread_class
                threadStart = thread_start
                threadInit = thread_init
                threadStop = thread_stop

                if addActions == 'pass':
                    addActions = ''
            else:
                threadClass = ''
                threadStart = 'pass'
                threadInit = ''
                threadStop = 'pass'

            formatted = dict(
                ThreadClass=threadClass,
                ThreadInit=threadInit,
                ThreadStart=threadStart,
                ThreadStop=threadStop,
                ActionClass=actionClass,
                ActionText=actionText,
                AddAction=addActions,
                RegisterPlugin=''.join(list(PrettyPythonPrint(*item) for item in text))[:-2],
                PluginName=str(text[0][1]).replace('-', '').replace(' ', '').strip()
            )

            text = REGISTER_PLUGIN.format(**formatted)

            if self.ctrl:
                self.ctrl.SetValue(text)
                self.frame.Show()
                self.frame.Raise()
            else:
                width = 80 * 6
                height = 17 * len(text.splitlines())
                self.frame = wx.Frame(self, size=(width + 30, height + 30))
                sizer = wx.BoxSizer(wx.HORIZONTAL)
                self.ctrl = wx.TextCtrl(
                    self.frame,
                    -1,
                    text,
                    size=(width, height),
                    style=wx.TE_MULTILINE | wx.TE_READONLY
                )

                def OnFrameClose(evt):
                    self.frame = None
                    self.ctrl = None
                    evt.Skip()

                self.frame.Bind(wx.EVT_CLOSE, OnFrameClose)
                sizer.Add(self.ctrl, 0, wx.EXPAND | wx.ALL, 10)
                self.frame.SetSizer(sizer)
                self.frame.Show()

            evt.Skip()

        def OnClose(evt):
            if self.frame:
                self.frame.Show(False)
                self.frame.Destroy()
           
            delattr(eg.globals, 'RegisterPluginApp')
            self.Show(False)
            self.Destroy()
           
        self.Bind(wx.EVT_CLOSE, OnClose)
        closeButton = wx.Button(self, -1, 'Close')
        viewButton = wx.Button(self, -1, 'View')
        closeButton.Bind(wx.EVT_BUTTON, OnClose)
        viewButton.Bind(wx.EVT_BUTTON, OnView)

        bSizer = wx.StdDialogButtonSizer()
        bSizer.Add(closeButton)
        bSizer.Add(viewButton)
        bSizer.Realize()

        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        buttonSizer.Add((3, 3), 1)
        buttonSizer.Add(bSizer, 0, wx.TOP | wx.BOTTOM, 6)
        buttonSizer.Add((3, 3), 0)

        def LineSizer(sizer, *widgets):
            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
            for i, widget in enumerate(widgets):
                if i + 1 == len(widgets):
                    args = (wx.EXPAND,)
                else:
                    args = (wx.EXPAND | wx.RIGHT, 20)
                lineSizer.Add(widget, 0, *args)
            sizer.Add(lineSizer, 0, wx.EXPAND | wx.ALL, 10)

        def MultiSizer(sizer, widget1, widget2):
            sizer.Add(widget1, 0, wx.ALIGN_CENTER | wx.EXPAND | wx.ALL, 10)
            sizer.Add(widget2, 0, wx.EXPAND | wx.ALL, 10)

        LineSizer(leftSizer, nameSt, nameCtrl)
        LineSizer(leftSizer, authorSt, authorCtrl)
        LineSizer(leftSizer, kindSt, kindCtrl)

        LineSizer(middleSizer, urlSt, urlCtrl)
        LineSizer(middleSizer, versionSt, versionCtrl)
        LineSizer(middleSizer, verTypeSizer)

        LineSizer(rightSizer, guidSt, guidCtrl)
        LineSizer(rightSizer, macroSt, macroCtrl)
        LineSizer(rightSizer, multiloadSt, multiloadCtrl)

        MultiSizer(leftMultiSizer, descSt, descCtrl)
        MultiSizer(leftMultiSizer, helpSt, helpCtrl)
        MultiSizer(rightMultiSizer, hardwareSt, hardwareCtrl)
        MultiSizer(rightMultiSizer, iconSt, iconCtrl)
        LineSizer(rightMultiSizer, iconBaseSizer)

        LineSizer(mainSizer, leftSizer, middleSizer, rightSizer)
        LineSizer(mainSizer, leftMultiSizer, rightMultiSizer)

        option_sizer = wx.BoxSizer(wx.HORIZONTAL)

        option_sizer.Add(action_st, 0, wx.ALL, 5)
        option_sizer.Add(action_ctrl, 1, wx.EXPAND | wx.ALL, 5)
        mainSizer.Add(option_sizer, 0, wx.EXPAND)
        option_sizer = wx.BoxSizer(wx.HORIZONTAL)
        option_sizer.Add(thread_st, 0, wx.ALL, 5)
        option_sizer.Add(thread_ctrl, 0, wx.ALL, 5)
        mainSizer.Add(option_sizer, 0, wx.EXPAND)
        LineSizer(mainSizer, buttonSizer)
        self.SetSizer(mainSizer)


try:
    eg.globals.RegisterPluginApp.Iconize(False)
    eg.globals.RegisterPluginApp.Raise()
except:
    try:
        delattr(eg.globals, 'RegisterPluginApp')
    except:
        pass

    frame = eg.globals.RegisterPluginApp = Frame()   
    frame .CenterOnParent()
    frame .Show()
    frame .Raise()



check it out and see if it will help ya


and just a tip. but all of the duplicate code for sending via urllib can be done in a single method in the plugin class. add a method for what data you want to send and then access it in the actions using self.plugin.METHODNAME. this will enable you to remove the use of globals as an example. globals ip would become self.ip instead. anything that is in the plugin class can be accessed from the actions by using self.plugin. so in an action if you wanted to access the ip you set in the plugin you would use self.plugin.ip
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Sat Jun 03, 2017 9:31 am

sorry i had to delete that other post. there seems to be something stuck with file attachments on the forum. and your post was the last one to have a file attachment
and it also was not displaying properly. so i deleted it. and i am sorry for having to do so
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Sat Jun 03, 2017 9:34 am

it appears as tho the forum posting has been fixed with the deletion of your post.


and here is a version of that plugin file that i went through. it should give you some ideas. I do not know if it will run but give it a go and see what happens. but at the very least it will give you some ideas i am sure
Attachments
ELVIPIO.py
(13.7 KiB) Downloaded 34 times
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby ottisaft » Sun Jun 04, 2017 7:16 am

That really 8)

My first impression is that a have to learn a lot :D. But your piece of code gives me an idea of the meaning of object orientated programming. Quite hard for me because I stopped programming in my youth in the 80s (BASIC) :lol:

I gave it a try and there seems to be a bug with the refresh variable. I'll try to figure it out.

Again; million thanks for your help!
User avatar
ottisaft
 
Posts: 3
Joined: Fri May 19, 2017 11:00 am
Location: Germany

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Sun Jun 04, 2017 9:55 am

You can get back into it. you wrote the plugin. all I did was format it out a bit differently. so you have an idea of what's going on. And i was right there with you 2 years ago. only experience i had was typing the code in that was in a book for the trs-80 color computer (radio shack). and that was the extent of my programming knowledge. and by all means please feel free to ask me any questions you want. if I have the answer i will give it. and if i don't i will BS my way through it.. nah I will get the answer for ya.
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby topix » Sat Jun 10, 2017 12:11 pm

OMG :D that's an old (but nice) piece of hardware. I remember that for a friend i wrote a simple plugin for it (never released it). Searched the archives on my NAS and found it. wow, december 2008 :)
topix
Experienced User
 
Posts: 350
Joined: Sat May 05, 2007 3:43 pm
Location: Germany

Re: ELV IPIO88 In/Out Interface plugin

Postby anagrok » Sun Jun 18, 2017 6:00 am

Yes, it's quite old, but it works for me perfectly. @kgschlosser: Thanks for your support. I went through your modifications. Was very helpful, but finally I failed to get rid of the global variables :(. However, I included everything, I found useful.
Here is the latest version. Runs smoothly in my home automation project now :D
Attachments
__init__.py
Ver. 0.2.1
(14.9 KiB) Downloaded 22 times
anagrok
 
Posts: 2
Joined: Mon Mar 09, 2015 8:40 pm

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Mon Jun 19, 2017 12:52 am

I haven't looked at it yet. My internet is giving me a hard hour so I am forced to use my phone. But you can get rid of the globals simply by setting the attribute to self

So ip would be self.ip instead.

And if you need to access the IP from an action you would use self.plugin.ip

self.plugin is your plugin instance. It has been added to your actions by eg.ActionBase as a convince thing. So if you have repeat code for connecting to the device. This can be centralized into the plugin. So if you put the repeating send code into a method called send that is inside of your plugin


def send(self, params):


You can use it in your actions by using self.plugin.send(params)
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Mon Jun 19, 2017 5:44 am

ok so check this out...

I only did some reformatting and combined some of the repeat code but I also removed the use of global
Attachments
__init__.py
(16.09 KiB) Downloaded 26 times
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby ottisaft » Fri Jul 14, 2017 3:17 pm

Yeah, it runs like a charm now. Bought a 2nd interface and struggled with my global variables :? using the plugin twice. But now it works perfectly. Thanks a million! Here is the latest version (deleted one small typo :wink: , thats it)
Attachments
__init__.py
(16.16 KiB) Downloaded 21 times
User avatar
ottisaft
 
Posts: 3
Joined: Fri May 19, 2017 11:00 am
Location: Germany

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Fri Jul 14, 2017 4:00 pm

dude it looks good. formatting is right..

It's easier to read isn't it? once you get used to what to look for.

you are within the 79 character limit. you noticed that not everything with ()'s means it's a tuple. if it doesn't have a comma in it it's not a tuple. when used with a string is is exactly the same as doing

Code: Select all
var = 'This is a '
var += 'line to show '
var += 'how you can '
var += 'make this one '
var += 'line.'


better this way

Code: Select all

var = (
    'This is a '
    'line to show '
    'how you can '
    'make this one '
    'line.'
)


it does the exact same thing. except at compile time it will make a single string. where as doing the += it makes function calls to add the pieces together. i know it's not alot but it does take some processor time to do it.

just make sure that when you do it you put 4 spaces before each of the extra lines. this is the identifier that it is code continuation

it takes time to get used to it. but once you have the hang of it. it's second nature.

As a start i used sublime text as an editor but then i changed over to a full fledged IDE called PyCharm.
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Fri Jul 14, 2017 4:06 pm

also as a suggestion you do not have to put the help strings into the actual config dialog. you can do this instead

Code: Select all
class GetOutputState(eg.ActionBase):
    name = "Get single Output State "
    description = (
           "Gets a single output state.\n\n"
            "Please configure output channel you want to read.\n"
            "Channel number between 1 and 8 is allowed."
        )


    def __call__(self, OutChannel):

        OutChannel = str(OutChannel)

        if not OutChannel.isdigit():
            self.plugin.PrintNotice(": Invalid Channel Number!")
            return

        OutChannelRead = int(OutChannel)

        if 1 <= OutChannelRead <= 8:
            self.plugin.Print(
                ": Reading Output channel Nr: %d ..." % OutChannelRead
            )

            self.plugin.out_status[OutChannelRead] = "?"

        else:
            self.plugin.PrintNotice(": Invalid Channel Number!")

    def Configure(self, OutChannel="1"):
       
        panel = eg.ConfigPanel(self)
        inStringEdit = panel.TextCtrl(OutChannel)
        panel.AddLine("Channel number: ", inStringEdit)

        while panel.Affirmed():
            panel.SetResult(inStringEdit.GetValue())



moving it to the description is the best place for it. what will take place is you will make the first line be the description of the action. then by having a blank line will indicate to EventGhost that the rest is Help for the action and it will then create a help tab in the Config Dialog. (I am pretty sure it works this way.. LOL :shock: ) I would have to check and see how the description gets parsed. you may need to replace the \n's with <br>
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: ELV IPIO88 In/Out Interface plugin

Postby kgschlosser » Fri Jul 14, 2017 4:13 pm

but also you can force the user to only be able to select specific values in the config dialog


Code: Select all
class GetOutputState(eg.ActionBase):
    name = "Get single Output State "
    description = (
           "Gets a single output state.\n\n"
            "Please configure output channel you want to read.\n"
            "Channel number between 1 and 8 is allowed."
        )


    def __call__(self, OutChannel):
        try:
            OutChannelRead = int(OutChannel)
        except ValueError:
            self.plugin.PrintNotice(": Invalid Channel Number!")
            return

        if 0 < OutChannelRead < 9:
            self.plugin.Print(
                ": Reading Output channel Nr: %d ..." % OutChannelRead
            )

            self.plugin.out_status[OutChannelRead] = "?"
        else:
            self.plugin.PrintNotice(": Invalid Channel Number!")

    def Configure(self, OutChannel=1):
        panel = eg.ConfigPanel(self)
        inStringEdit = panel.SpinIntCtrl(OutChannel, min=1, max=8)
        panel.AddLine("Channel number: ", inStringEdit)

        while panel.Affirmed():
            panel.SetResult(inStringEdit.GetValue())
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
 
Posts: 2702
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA


Return to Plugin Support

Who is online

Users browsing this forum: No registered users and 6 guests