eplan

XAfActionSettingProject Beispiel

Neu mit EPLAN V2.3 kam die Action XAfActionSettingProject hinzu…

Die Action ermöglicht das hinzufügen von Sprachen zum aktuellen Projekt.

Anbei ein Beispielaufruf, netterweise von Frank Schöneck bereitgestellt :^)

public class Script
{
    [Start]
    public void XAfActionSettingProject_Start()
    {
        CommandLineInterpreter oCLI = new CommandLineInterpreter();
        ActionCallingContext oACC = new ActionCallingContext();
        oACC.AddParameter("set", "TRANSLATEGUI.TRANSLATE_LANGUAGES");
        oACC.AddParameter("value", "de_DE;en_EN;zh_CN;");

        oCLI.Execute("XAfActionSettingProject", oACC);
        return;
    }
}
Von |2017-11-09T12:23:43+01:002014-03-06|EPLAN, EPLAN-Scripts|

Doorbell – Teil 1: Schaltplan und Programm

War irgendwann klar dass ich mir einen Raspberry Pi hole, fand auch (natürlich erst nach dem Kauf) einen Anwendungsfall >>> unsere Türklingel.

Funktion JETZT:
Klingel ist an ISDN-Anlage (ohne sonstige Funktion) angeschlossen. Telefon klingelt wenn jemand an der Tür leutet.

Funktion SOLL:
Jemand klingelt, Audio wird abgespielt, Bild wird vom Besucher gemacht, Upload per SFTP auf Webserver, Pushmessage auf iPhone/iPad/Android

Die Schaltung ist überschaubar. Verwende einen Pullup / Pulldown Resistor (muss noch testen was besser funktioniert, da ich gemerkt habe dass statische Aufladung den Eingang setzt). Eine LED für die Anzeige dass das Python-Script läuft und eine LED für Aktivierung der Doorbell-Funktion.

Doorbell_Schaltplan

Hab es jetzt zum testen auf eine Steckplatine aufgebaut, funktioniert soweit. Werde es aber noch auf eine Platine löten, damit dass schön kompakt wird.

Zuerst wollte ich das ganze mit Mono programmieren, da ich Mono noch eine Chance geben wollte. Aber da es an einigen Ecken zu beginn schon zum knarzen begann, habe ich auf Python zurückgegriffen.

Finde Python keine schöne Sprache, aber mächtig. Naja, mein Anwendungsfall ist überschaubar, somit auch die paar Zeilen Programmcode.

Ich gehe hier nicht auf die Standard-Funktionen des Raspberrys ein, da es viele gute Anleitungen im Internet gibt.

Initialisierung

Alle benötigten Abhängigkeiten + Eventhandler (ausschalten der Status-LED) + Logging Methode. Wichtig ist hier auch noch das Audio auf 100% zu stellen. Da ich das Signal per Funk an Boxen weitergebe, ist hier wichtig dass der AUX Anschluss auf Maximum ist. Als letztes werden die IOs konfiguriert.

from time import gmtime, strftime, sleep
from datetime import datetime
import RPi.GPIO as GPIO
import os
import subprocess
import os.path
import httplib, urllib
import pysftp
import atexit
import traceback
import logging
import time

# On exit
def exit_handler():
    GPIO.output(22, False)
atexit.register(exit_handler)

# Logging
logger = logging.getLogger('doorbell')
hdlr = logging.FileHandler('/home/pi/Desktop/doorbell/web/doorbell.txt')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)

# Start
print(strftime("%Y-%m-%d %H:%M:%S", gmtime()) + " Doorbell started")
logger.info("Doorbell started")

# Volume
cmdVolume='amixer set PCM -- 1000'
subprocess.call(cmdVolume, shell=True)

# Pins
GPIO.setmode(GPIO.BOARD)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
GPIO.output(15, False)
GPIO.output(22, True)
GPIO.setup(11, GPIO.IN)

Alles eingepackt in eine While-Dauerschleife für ich folgenden Code nacheinander aus:

# Setup
now=strftime("%Y-%m-%d %H:%M:%S", gmtime())
filename=strftime("%Y-%m-%d_%H.%M.%S", gmtime())  + '.jpg'

print(now + " Button pressed")
logger.info("Button pressed")
GPIO.output( 15, True)

Hier wird einfach nur geloggt, wenn der Button gedrückt wurde (Datum, Uhrzeit) und zusätzlich die LED für den Programmablauf eingeschaltet. Ich speichere mir gleich das Datum in eine Variable um es später für die Bilddatei zu verwenden.

# Audio
print("--> Audio")
logger.info("--> Audio")
subprocess.Popen(['aplay', '/home/pi/Desktop/doorbell/ringtone.wav'])

Nun spielen wir das Audiofile (in meinem Fall eine WAV-Datei) ab. Hier ist die Besonderheit dass es parallel zum Ablauf des Scripts passiert. Dass heißt hier wird ein separater Thread gestartet. Achja, TIP: nehmt am besten einen nervigen Sound (habe mich für Super Mario 1 Theme entschieden) dass kommt in der Frauenwelt sehr gut an :^)

# Camera
print("--> Camera")
logger.info("--> Camera")
cmdCam='raspistill -o ' + '/home/pi/Desktop/doorbell/web/photos/' +  filename
subprocess.call(cmdCam, shell=True)

Der Kamera Aufruf ist denkbar einfach. Hier habe ich versucht auch im separaten Thread das Bild zu speichern, hatte aber bei jedem 10. Bild ein Problem, welches ich (noch) nicht nachvollziehen konnte. Ihr seht schon dass sich die Bilder in einem Ordner web befinden. Ich habe mich im Nachhinein dafür entschieden einen Webserver auf dem Pi laufen zu lassen. Dadurch hab ich mehr Kontrolle und kann von außen auch z.B. einen Livestream der Cam anschauen sowie die Logdatei oder einfach per SSH verbinden.

Wie oben erwähnt habe ich angedacht per SFTP das Bild auf meinen Webserver bei Uberspace zu laden. Habe ich auch getestet und das wäre der Code dafür (auskommentiert):

# Upload Foto
#print("--> Upload")
#logger.info("--> Upload")
#srv = pysftp.Connection(host="MeinServer.de", username="MyUsername",
#                        password="MyPassword", log="True")
#srv.chdir("/Mein/Ordner/Mit/Photos/Auf/Server")
#srv.put('/Mein/Ordner/Mit/Photos/Lokal/' + filename)
#srv.close()

Nun zum Teil der mir am meisten Spaß gemacht hat. Funktion ist genial und einfach zu implementieren. Der Dienst nennt sich Pushover, ist für meine Anwendung kostenlos da ich unter 7500 Pushes im Monat bleibe (außer ich bekomme sehr viel Besucher). Die API ist sehr gut dokumentiert und es gibt Beispiele für viele Sprachen.

# Pushover
print("--> Pushover")
logger.info("--> Pushover")
conn = httplib.HTTPSConnection("api.pushover.net:443")
conn.request("POST", "/1/messages.json",
             urllib.urlencode({
                              "token": "app-token",
                              "user": "user-token",
                              "title": "Doorbell",
                              "message": "KNOCK KNOCK",
                              "url": "http://irgendwo.de/photos/" + filename,
                              "url_title": "Image",
                              }),
             { "Content-type": "application/x-www-form-urlencoded" })
conn.getresponse()

Das ganze wird bei mir wie erwähnt auf Android, iPad und iPhone gepusht und dauert ca. 1-3 Sekunden nach drücken der Klingel, was mehr als ausreicht.

2013-11-30 00.11.54 2013-11-30 00.10.19  2013-11-30 00.10.23

 

Lockscreen > Pushover App Übersicht > Detail

Mit einem Tap auf Image wird mir dann auch das Bild des Besuchers angezeigt. Die Farben sind Tagsüber OK. In der nacht wird das ganze schwarz/weiß, aber die Qualität und Erkennbarkeit ist durchgehend gut.

2013-11-30 08.30.54

Hier sei erwähnt dass ich nicht die Standard Raspberry Pi Camera gekauft habe sondern die IR-Version.

Zusätzlich habe ich mir einen HTTP-Livestream gebaut, damit ich per iPhone/iPad die Kamera live betrachten kann (diente nur zum einstellen).

Anbei das ganze Script:

from time import gmtime, strftime, sleep
from datetime import datetime
import RPi.GPIO as GPIO
import os
import subprocess
import os.path
import httplib, urllib
import pysftp
import atexit
import traceback
import logging
import time

# On exit
def exit_handler():
    GPIO.output(22, False)
atexit.register(exit_handler)

# Logging
logger = logging.getLogger('doorbell')
hdlr = logging.FileHandler('/home/pi/Desktop/doorbell/web/doorbell.txt')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)

# Start
print(strftime("%Y-%m-%d %H:%M:%S", gmtime()) + " Doorbell started")
logger.info("Doorbell started")

# Volume
cmdVolume='amixer set PCM -- 1000'
subprocess.call(cmdVolume, shell=True)

# Pins
GPIO.setmode(GPIO.BOARD)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
GPIO.output(15, False)
GPIO.output(22, True)
GPIO.setup(11, GPIO.IN)

# Loop
while 1:
    if GPIO.input(11):
        try:
            # Setup
            now=strftime("%Y-%m-%d %H:%M:%S", gmtime())
            filename=strftime("%Y-%m-%d_%H.%M.%S", gmtime())  + '.jpg'

            print(now + " Button pressed")
            logger.info("Button pressed")
            GPIO.output( 15, True)

            # Audio
            print("--> Audio")
            logger.info("--> Audio")
            subprocess.Popen(['aplay', '/home/pi/Desktop/doorbell/ringtone.wav'])

            # Camera
            print("--> Camera")
            logger.info("--> Camera")
            cmdCam='raspistill -o ' + '/home/pi/Desktop/doorbell/web/photos/' +  filename
            subprocess.call(cmdCam, shell=True)

            # Pushover
            print("--> Pushover")
            logger.info("--> Pushover")
            conn = httplib.HTTPSConnection("api.pushover.net:443")
            conn.request("POST", "/1/messages.json",
                         urllib.urlencode({
                                          "token": "app-token",
                                          "user": "user-token",
                                          "title": "Doorbell",
                                          "message": "KNOCK KNOCK",
                                          "url": "http://irgendwo.de/photos/" + filename,
                                          "url_title": "Image",
                                          }),
                         { "Content-type": "application/x-www-form-urlencoded" })
            conn.getresponse()

            # Finished
            print("--> Finished")
            logger.info("--> Finished")
            time.sleep(2)

        except Exception, e:
            traceback.print_exc()
            logging.exception("!!!")
    else:
        GPIO.output( 15, False)

 

Projektübersicht

Von |2014-07-24T12:14:44+02:002013-11-30|Coding, Doorbell, Projekte, Raspberry Pi|

DeciderDisplayEnable

Das kleine Script erlaubt es, die unterdrückten Meldungen wieder einzeln zu aktivieren.

Vielen Dank an FrankS für die Umsetzung!

DeciderDisplayEnable

DeciderDisplayEnable (1567 Downloads )

 

// DeciderDisplayEnable, Version 1.0.0, vom 25.09.2013
//
// Zeigt alle Unterdrückten Meldungen in einer Liste an
// und ermöglicht durch entfernen der jeweiligen Checkbox
// das wiederanzeigen der unterdrückten Meldung.
//
// Copyright by Frank Schöneck, 2013
// letzte Änderung: Frank Schöneck, 25.09.2013 V1.0.0, -Projektbeginn
//
// für Eplan Electric P8, V2.2 / V2.3
//
using System.Windows.Forms;
using Eplan.EplApi.Scripting;
using Eplan.EplApi.Base;

public partial class frmDeciderDisplayEnable : System.Windows.Forms.Form
{
	[Start]
	public void Function()
	{
		//Form anzeigen
		frmDeciderDisplayEnable frm = new frmDeciderDisplayEnable();
		frm.ShowDialog();

		return;
	}

	private void frmDeciderDisplayEnable_Load(object sender, System.EventArgs e)
	{
		Settings oSettings = new Settings();
		string sDeciderNotDisplay = string.Empty;
		int iCountDeciderNotDisplay = 0;
		ListViewItem objListViewItem = new ListViewItem();

		if (oSettings.ExistSetting("USER.Decider.NotDisplay"))
		{
			//Anzahl Settings ermitteln
			iCountDeciderNotDisplay = oSettings.GetCountOfValues("USER.Decider.NotDisplay");

			//in ListView einlesen
			for (int n = 0; n < iCountDeciderNotDisplay; n++)
			{
				sDeciderNotDisplay = oSettings.GetStringSetting("USER.Decider.NotDisplay", n);
				objListViewItem = new ListViewItem();
				objListViewItem.Text = sDeciderNotDisplay;
				objListViewItem.Checked = true;
				objListViewItem.SubItems.Add(n.ToString());
				listView1.Items.Add(objListViewItem);
			}
		}
	}

	//Button OK
	private void btnOK_Click(object sender, System.EventArgs e)
	{
		Settings oSettings = new Settings();

		//Setting löschen!
		oSettings.DeleteSetting("USER.Decider.NotDisplay");

		//Setting nach löschen wieder neu anlegen
		oSettings.AddStringSetting("USER.Decider.NotDisplay",
		new string[] { },
		new string[] { }, "DeciderDisplayEnable",
		new string[] { "Default value of DeciderDisplayEnable" },
		ISettings.CreationFlag.Insert);

		int n = 0; //Zähler starten

		//Listview abarbeiten
		foreach (ListViewItem itemRow in listView1.Items)
		{
			if (itemRow.Checked) //wenn Ausgewählt Setting schreiben
			{
				//Setting schreiben
				oSettings.SetStringSetting("USER.Decider.NotDisplay", itemRow.Text, n);
				n++; //Zähler für VAL erhöhen
			}
		}

		//Beenden
		Close();
	}

	//Button Abbrechen
	private void btnAbbrechen_Click(object sender, System.EventArgs e)
	{
		Close();
	}
}
Von |2017-11-09T12:23:43+01:002013-09-27|EPLAN, EPLAN-Scripts|

CopyMode

Um die Modi des Kopierens schnell und einfach zu wechseln, hat Luc Morin ein Script geschrieben. Vielen Dank an dieser Stelle nach Kanada!

12-08-2013 12-15-57

CopyMode (1551 Downloads )

 

/*
Copyright (c) 2013 STLM Inc.

This program 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 3 of the License, or
(at your option) any later version.

This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using Eplan.EplApi.Scripting;

public class STLMCopy
{
    //Add the two actions as menu points under Utilities
    [DeclareMenu]
    public void CopyNormalMenu()
    {
        Eplan.EplApi.Gui.Menu oMenu = new Eplan.EplApi.Gui.Menu();
        oMenu.AddMenuItem("Copy (Normal Mode)", "NormalCopyAction");
        oMenu.AddMenuItem("Copy (Design Mode)", "DesignCopyAction");
    }

    //Declare the action to force copy in normal mode
    [DeclareAction("NormalCopyAction")]
    public void NormalCopyAction()
    {
        bool toggled = false;

        if (DesignModeState)
        {
            ToggleDesignMode();
            toggled = true;
        }

        Copy();

        if (toggled)
            ToggleDesignMode();
    }

    //Declare the action to force copy in design mode
    [DeclareAction("DesignCopyAction")]
    public void DesignCopyAction()
    {
        bool toggled = false;

        if (!DesignModeState)
        {
            ToggleDesignMode();
            toggled = true;
        }

        Copy();

        if (toggled)
            ToggleDesignMode();
    }

    //Helper functions and properties

    private bool DesignModeState
    {
        get
        {
            return new Eplan.EplApi.Base.Settings().GetBoolSetting("USER.GedViewer.ConstructionMode", 0);
        }
    }

    private void ToggleDesignMode()
    {
        Eplan.EplApi.ApplicationFramework.ActionManager mgr = new Eplan.EplApi.ApplicationFramework.ActionManager();

        Eplan.EplApi.ApplicationFramework.Action act = mgr.FindAction("XGedActionToggleConstructionMode");
        if (act != null)
        {
            Eplan.EplApi.ApplicationFramework.ActionCallingContext ictx = new Eplan.EplApi.ApplicationFramework.ActionCallingContext();
            act.Execute(ictx);
        }
    }

    private void Copy()
    {
        Eplan.EplApi.ApplicationFramework.ActionManager mgr = new Eplan.EplApi.ApplicationFramework.ActionManager();

        Eplan.EplApi.ApplicationFramework.Action act = mgr.FindAction("XGedStartInteractionAction");
        if (act != null)
        {
            Eplan.EplApi.ApplicationFramework.ActionCallingContext CopyCtx = new Eplan.EplApi.ApplicationFramework.ActionCallingContext();
            CopyCtx.AddParameter("Name", "XMIaClipboardCopy");
            act.Execute(CopyCtx);
        }
    }

}
Von |2017-11-09T12:23:43+01:002013-08-12|EPLAN, EPLAN-Scripts|
Nach oben