roverte
Posts: 2
Joined: Mon Sep 09, 2019 7:05 pm

Problem Using Telnet and PIGPIO at the Same Time

Mon Sep 09, 2019 7:21 pm

I've been working on a project in Python to integrate two different control systems in my home and have run into an issue that I cannot figure out. I've spent a lot of time trying to debug this and the only thing that I can think might be causing the problem is that I'm trying to use the Telnet library to read information from one system and the PIGPIO library to send information to another system at the same time. Does anyone know if this is possible. If it is not possible, is there something I can do as a work around?

The basic set up is as follows:

-- Raspberry Pi connects to one system (Lutron) with Telnet and reads in information (button presses, etc.). This is all set up and the Pi can read and process button presses on the Lutron system.

-- Raspberry Pi connects to another system (Somfy) with an RF transmitter attached to GPIO. This is based on the work that Nickduino did (https://github.com/Nickduino/Pi-Somfy/b ... hutters.py). This is also set up and I can control my Somfy shades through my Python script.

-- The problem is that when a command comes in over Telnet, the script calls the functions to engage with the Somfy system but the RF transmitter does not do anything. As far as I can tell, the scripts are all executing correctly but nothing is getting sent to the RF transmitter. I've tried connecting the transmitter to GPIO 4 and 17 but neither is working when I access the function after getting a command in over Telnet. Both pins work when I do not run it based on a Telnet input.

Happy to share my code if that would be helpful. (Although it's a bit rough as I have not done much programming since college.) Would appreciate any suggestions or thoughts that you may have.

Thanks so much!

User avatar
MrYsLab
Posts: 369
Joined: Mon Dec 15, 2014 7:14 pm
Location: Noo Joysey, USA

Re: Problem Using Telnet and PIGPIO at the Same Time

Tue Sep 10, 2019 4:36 pm

Sharing the code sounds like a good idea. If you are going to post it here, please use the "Code" tag as described on this link: https://www.raspberrypi.org/forums/view ... 32&t=84477

roverte
Posts: 2
Joined: Mon Sep 09, 2019 7:05 pm

Re: Problem Using Telnet and PIGPIO at the Same Time

Thu Sep 12, 2019 1:36 pm

Thanks so much. Below I've added my code for (1) the primary script (LutronInputSomPi.py) and (2) the separate file with code to connect to the Somfy motors (SomPiController_nogpio.py). (Ignore the file name; I named it that way for now because I moved the GPIO initialization function to the primary file.)

The Somfy control works fine when called through the shade_drive function. The terminal output is also correct when I try to control the Somfy through the parse_events function but the RF transmitter does not engage, which makes me think that it is having an issue accessing the GPIO port. I've tried this on GPIO4, 5 and 17.

Would really appreciate any help or advice on debugging this.

Thanks,
Alex

LutronInputSomPi.py

Code: Select all

#!/usr/bin/env python

import telnetlib
import re
import time
import sys
import traceback
#import pigpio

# Load Lutron configuration
import LoadConfig
# Load Somfy controller
import SomPiController_nogpio


## Enter IP address of Lutron hub.
HOST = "192.168.1.236"

## Default passwords for Lutron hub.
LOGIN = "lutron"
PASSWORD = "integration"
EVENT_RE = re.compile('\S*\s?~(\w+),(\d+),(\d+),(\d+.?\d*)')

## Name of file with parsed site configuration.
RAW_CONFIG_FILE = "siteconfig"

TXGPIO=5 # 433.42 MHz emitter on GPIO 5

################################################
###  Functions to read configuration of Lutron devices.
################################################

def get_lutron_config():
## Import configuration of Lutron devices
    DEVICES = []
    HUBS, SWITCHES, PICOS, SHADEPICOS = LoadConfig.load_integration(RAW_CONFIG_FILE)
    print("Configuration loaded.")
    return(HUBS, SWITCHES, PICOS, SHADEPICOS)

################################################
###  Functions to connect to the Lutron hub and send/receive commands.
################################################

def connect():
## Telnet connection to Lutron hub.
    tn = telnetlib.Telnet(HOST)
    tn.read_until(b"login: ")
    tn.write(LOGIN.encode('ascii') + b"\r\n")
    tn.read_until(b"password: ")
    tn.write(PASSWORD.encode('ascii') + b"\r\n")
    print("Connected to Lutron.")
    return(tn)

def send_command(tn):
## Send command to a Lutron switch.
    time.sleep(0.3)
    (device, level) = command_input()
    if int(device) in SWITCHES:
        command = "#OUTPUT," + device + ",1," + level + ",00:02"
    elif int(device) in PICOS:
        command = "#DEVICE," + device + "," + level + ",3"
        time.sleep(0.3)
        command = "#DEVICE," + device + "," + level + ",4"
    else:
        print("Error")
        return
    tn.write(command.encode('ascii') + b"\r\n")
    time.sleep(2.3)

    if int(device) in SWITCHES:
        get_status(tn, device)
    elif int(device) in PICOS:
        get_status(tn, device)

def get_status(tn, device):
## Get status of a switch.
    command = "?OUTPUT," + str(device) + ",1"
    tn.write(command.encode('ascii') + b"\r\n")
    recv = tn.read_until(b"\r\n")
    parse_events(recv)
    print()
    print()

def parse_events(event):
## Identify type of device sending report (Pico or switch)
    action, device, button, var = event[0], event[1], event[2], event[3]
    device = int(device)
    button = int(button)
    var = int(var[0])
    if device in PICOS:
        print("Pico No. {}, Button No. {}".format(device, button), end="")
        if var == 3:
            print(" pressed.")
        elif var == 4:
            print(" released.")
        else:
            print(" invalid.")

    elif device in SHADEPICOS:
        print("Pico No. {}, Button No. {}".format(device, button))
        shade_name = "Nook"
        command = ""
        if var == 3:
            if button == 2:
                print("Shade " + str(device) + " raise all the way.")
                command = "open"
            elif button == 4:
                print("Shade " + str(device) + " lower all the way.")
                command = "close"
            elif button == 5:
                print("Shade " + str(device) + " raise until release.")
                command = "open"
            elif button == 6:
                print("Shade " + str(device) + " lower until release.")
                command = "close"
            elif button == 3:
                print("Shade " + str(device) + " stop.")
                command = "stop"
            else:
                print("No function.")

        elif var == 4:
            if button == 5:
                print("Shade " + str(device) + " stop raising.")
                command = "stop"
            elif button == 6:
                print("Shade " + str(device) + " stop lowering.")
                command = "stop"
            else:
                print("No function.")

        else:
            print("Error.")

        if command != "":
            frame = SomPiController_nogpio.shade_command(shade_name, command)
            SomPiController_nogpio.send_shade_command(frame, TXGPIO)

    elif int(device) in SWITCHES:
        switches_out(event)

def switches_out(event):
# Parse output from switch to be readable
    action, device, button, var = event[0], event[1], event[2], event[3]
    print("Switch No. {}: {}".format(device, var))

def logout():
## Logout from Telnet hub.
    tn.close()
    print("Connection closed.")

################################################
###  User inputs
################################################

def menu():
## Menu of available commands
    for i in range(40):
        print("+", end="")
    print("")
    while True:
        options = [1, 2, 3, 4, 5]
        print("Available Options:")
        print("1.  Monitor Events")
        print("2.  Send Command")
        print("3.  Get Status")
        print("4.  Shade Drive")
        print("5.  Exit")
        selection = input("Make selection: ")
        try:
            test = int(selection)
            if int(selection) in options:
                break
            else:
                print("Invalid entry. ", end="")
        except ValueError:
            print("Invalid entry. ", end="")

    return selection

def monitor_events(tn):
## Continuous monitoring of events on the Lutron network.
    print("Monitoring for events.  Press Control+C for Menu of commands.")
    while True:
        try:
            recv = tn.read_until(b"\r\n")
            for event in EVENT_RE.findall(str(recv)):
                parse_events(event)
        except KeyboardInterrupt:
            print("")
            break

def command_input():
## User inputs the light switch to send a command to.
    while True:
        device = input("Enter device number: ")
        try:
            device = int(device)
        except ValueError:
            print("Invalid entry. ", end="")
            device = input("Enter device number: ")
        if int(device) in SWITCHES:
            while True:
                level = input("Enter brightness level from 0 - 100: ")
                try:
                    level = int(level)
                except ValueError:
                    print("Invalid entry. ", end="")
                    level = input("Enter brightness level from 0 - 100: ")
                if int(level) >= 0 and int(level) <= 100:
                    break
                else:
                    print("Cannot set switch no. " + str(device) + " to level " + str(level) + ".")
                    level = input("Enter brightness level from 0 - 100: ")
            return(str(device), str(level))
        elif int(device) in PICOS:
            while True:
                level = input("Enter button to press: ")
                try:
                    level = int(level)
                except ValueError:
                    print("Invalid entry. ", end="")
                    level = input("Enter button to press: ")
                if int(level) >= 0 and int(level) <= 6:
                    break
                else:
                    print("Cannot push button no. " + str(level) + " on pico no. " + str(device) + ".")
                    level = input("Enter button to press: ")
            return(str(device), str(level))
        else:
            print("No device no. " + str(device) + ". ", end="")



def status_ping(tn):
## Prompt user for device to check status of.
    while True:
        device = input("Enter switch number: ")
        try:
            device = int(device)
        except ValueError:
            print("Invalid entry. ", end="")
            device = input("Enter device number: ")
        if int(device) in SWITCHES:
            break
        else:
            print("No switch No. " + str(device) + ". ", end="")
    get_status(tn, device)

################################################
### Shade Connect
################################################

def shade_control_temp(event):
    shade_name = "Nook"
    ###
    ### Revise configuration read to take in the SOMFY ID
    ###
    action, device, button, var = event[0], event[1], event[2], event[3]
    var = int(var[0])
    button = int(button)
    if var == 3:
        if button == 2:
            print("Shade " + str(device) + " raise all the way.")
            SomPiController.shade_command("Nook", "open")
        elif button == 4:
            print("Shade " + str(device) + " lower all the way.")
            SomPiController.shade_command("Nook", "close")
        elif button == 5:
            print("Shade " + str(device) + " raise until release.")
            SomPiController.shade_command(shade_name, "open")
        elif button == 6:
            print("Shade " + str(device) + " lower until release.")
            SomPiController.shade_command(shade_name, "close")
        elif button == 3:
            print("Shade " + str(device) + " stop.")
            SomPiController.shade_command(shade_name, "stop")
        else:
            print("No function.")

    elif var == 4:
        if button == 5:
            print("Shade " + str(device) + " stop raising.")
            SomPiController.shade_command(shade_name, "stop")
        elif button == 6:
            print("Shade " + str(device) + " stop lowering.")
            SomPiController.shade_command(shade_name, "stop")
        else:
            print("No function.")

    else:
        print("Error.")

def shade_drive():
    shade = "Nook"

    print("Enter command")
    print("1.  Open")
    print("2.  Close")
    print("3.  Stop")
    print("4.  Register")


    while True:
        direction = input("Enter command: ")

        if int(direction) == 1:
            movement = "open"
        elif int(direction) == 2:
            movement = "close"
        elif int(direction) == 3:
            movement = "stop"
        elif int(direction) == 4:
            movement = "register"
        else:
            break

        frame = SomPiController_nogpio.shade_command(shade, movement)
        SomPiController_nogpio.send_shade_command(frame, TXGPIO)

################################################
###  Program
################################################

# Configure GPIO for RF transmission
SomPiController_nogpio.init_gpio(TXGPIO)

# Connect to Lutron
tn = connect()

# Load configuration of Lutron Devies
HUBS, SWITCHES, PICOS, SHADEPICOS = get_lutron_config()

print("Shade picos: ",SHADEPICOS)
print("Picos: ",PICOS)

monitor_events(tn)

while True:
    selection = int(menu())
    if selection == 1:
        monitor_events(tn)
    elif selection == 2:
        send_command(tn)
    elif selection == 3:
        status_ping(tn)
    elif selection == 4:
        shade_drive()
    elif selection == 5:
        break

logout()
SomPiController_nogpio.py

Code: Select all

# Python3
# -*- coding: utf-8 -*-

import sys
import pigpio
import traceback

#Button values
btnDown = 0x4
btnUp = 0x2
btnStop = 0x1
btnProg = 0x8

#TXGPIO=4 # 433.42 MHz emitter on GPIO 4

frame = bytearray(7)

#Function to send a frame
def shade_command(shade, action):
   checksum = 0

   #Defining button action
   if action == "open":
      button = btnUp
   elif action == "close":
      button = btnDown
   elif action == "stop":
      button = btnStop
   elif action == "register":
      button = btnProg
   else:
      print("Unknown action.")
      print("Please use open, close, stop or register.")
      sys.exit()
   print("Action       : " + action)
   print("Button       : ", button)
   #Defining shade
   print("Shade        : " + shade)

   #Reading remote
   #The files are stored in a subfolder called "remotes"
   with open("remotes/" + shade + ".txt", 'r') as file:
      data = file.readlines()

   remote = int(data[0], 16)
   code = int(data[1])
   data[1] = str(code + 1)

   with open("remotes/" + shade + ".txt", 'w') as file:
      file.writelines(data)

   print("Remote       : " + "0x%0.2X" % remote)
   print("Button       : " + "0x%0.2X" % button)
   print("Rolling code : " + str(code))

   frame[0] = 0xA7;                   # Encryption key. Doesn't matter much
   frame[1] = button << 4             # Which action did you chose? The 4 LSB will be the checksum
   frame[2] = code >> 8               # Rolling code (big endian)
   frame[3] = (code & 0xFF)           # Rolling code
   frame[4] = remote >> 16            # Remote address
   frame[5] = ((remote >>  8) & 0xFF) # Remote address
   frame[6] = (remote & 0xFF)         # Remote address

   print("Frame        :",)
   for octet in frame:
      print("0x%0.2X" % octet,)
   print("")

   for i in range(0, 7):
      checksum = checksum ^ frame[i] ^ (frame[i] >> 4)

   checksum &= 0b1111; # We keep the last 4 bits only

   frame[1] |= checksum;

   print("With cks     :",)
   for octet in frame:
      print("0x%0.2X" % octet,)
   print("")

   for i in range(1, 7):
      frame[i] ^= frame[i-1];

   print("Obfuscated   :",)
   for octet in frame:
      print("0x%0.2X" % octet,)
   print("")

   return(frame)

def init_gpio(TXGPIO):
    print("TXGPIO:      ", TXGPIO)
    #Connecting to Pi
    pi = pigpio.pi()
    if not pi.connected:
     exit()

    pi.wave_add_new()
    pi.set_mode(TXGPIO, pigpio.OUTPUT)

def send_shade_command(frame, TXGPIO):
#Telling what you want to send
    pi = pigpio.pi()

    wf=[]
    wf.append(pigpio.pulse(1<<TXGPIO, 0, 9415))
    wf.append(pigpio.pulse(0, 1<<TXGPIO, 89565))
    for i in range(2):
      wf.append(pigpio.pulse(1<<TXGPIO, 0, 2560))
      wf.append(pigpio.pulse(0, 1<<TXGPIO, 2560))
    wf.append(pigpio.pulse(1<<TXGPIO, 0, 4550))
    wf.append(pigpio.pulse(0, 1<<TXGPIO,  640))

    for i in range (0, 56):
      if ((frame[i // 8] >> (7 - (i%8))) & 1):
         wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
         wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
      else:
         wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
         wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))

    wf.append(pigpio.pulse(0, 1<<TXGPIO, 30415))

    #1
    for i in range(7):
      wf.append(pigpio.pulse(1<<TXGPIO, 0, 2560))
      wf.append(pigpio.pulse(0, 1<<TXGPIO, 2560))
    wf.append(pigpio.pulse(1<<TXGPIO, 0, 4550))
    wf.append(pigpio.pulse(0, 1<<TXGPIO,  640))

    for i in range (0, 56):
      if ((frame[i // 8] >> (7 - (i%8))) & 1):
         wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
         wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
      else:
         wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
         wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))

    wf.append(pigpio.pulse(0, 1<<TXGPIO, 30415))

    #2
    for i in range(7):
      wf.append(pigpio.pulse(1<<TXGPIO, 0, 2560))
      wf.append(pigpio.pulse(0, 1<<TXGPIO, 2560))
    wf.append(pigpio.pulse(1<<TXGPIO, 0, 4550))
    wf.append(pigpio.pulse(0, 1<<TXGPIO,  640))

    for i in range (0, 56):
      if ((frame[i // 8] >> (7 - (i%8))) & 1):
         wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))
         wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
      else:
         wf.append(pigpio.pulse(1<<TXGPIO, 0, 640))
         wf.append(pigpio.pulse(0, 1<<TXGPIO, 640))

    wf.append(pigpio.pulse(0, 1<<TXGPIO, 30415))

    pi.wave_add_generic(wf)
    wid = pi.wave_create()
    pi.wave_send_once(wid)
    while pi.wave_tx_busy():
      pass
    pi.wave_delete(wid)

    pi.stop()

User avatar
MrYsLab
Posts: 369
Joined: Mon Dec 15, 2014 7:14 pm
Location: Noo Joysey, USA

Re: Problem Using Telnet and PIGPIO at the Same Time

Thu Sep 12, 2019 8:02 pm

Have you tried using piscope http://abyz.me.uk/rpi/pigpio/piscope.html to monitor the gpio for output?
If you are seeing the waveforms generated when you execute LutronInputSomPi.py, are the waveforms and timing correct?

BTW here is a link in the forum on using piscope https://www.raspberrypi.org/forums/view ... p?t=168821

Return to “Python”