Monday, January 12, 2015

Stream The Raspberry Pi Camera over Websockets HTML5


I've been going through all the tutorials on how to get your pi camera to a webpage and hadn't found one that uses Websockets. So I tried it out and it worked quit well.

what you need:

  • Autobahn python websocket server
    • pip install autobahn[twisted]
  • picamera python library
    • http://www.raspberrypi.org/learning/python-picamera-setup/
  • My source at github:
    • source
    • You will have to copy the www directory to your '/usr/local/www' or change the source code to fit

The sample webpage on the github is a basic websocket client webpage that provides a couple of features.

Since my cam is hidden within a rpi picture frame (will blog soon on that project) there's a little black around the edges.  I circled the controls I wired into the websocket server. The buttons show a preview on the raspberry pi's screen. The slider changes the framerate (0-30 fps).

The stream is smooth but still delayed like most streams to the web.

I may make updates depending on interest but its not a priority on my list of pi projects.

Let me know in the comments :-)


Saturday, December 13, 2014

Raspberry Pi getting data from a S7-1200 PLC


UPDATE: If you want the raspberry pi to be the s7 server go here
UPDATE 2: If you want to see communication with S7-200 go here
UPDATE 3: Video walkthrough on setup go here

I recently borrowed a S7-1200 PLC from work to see if I could get data from it using a Raspberry Pi. In my search for something I found that Snap7 was the best option.
Steps to getting it work
  1. Download and compile snap7 (http://sourceforge.net/projects/snap7/files/1.2.1/snap7-full-1.2.1.tar.gz/download)
  2. Download and install python library to use snap7 (https://pypi.python.org/pypi/python-snap7)


#download and compile snap7 for rpi

wget http://sourceforge.net/projects/snap7/files/1.2.1/snap7-full-1.2.1.tar.gz/download 
tar -zxvf snap7-full-1.2.1.tar.gz
cd snap7-full-1.2.1/build/unix
sudo make –f arm_v6_linux.mk all

#copy compiled library to your lib directories
sudo cp ../bin/arm_v6-linux/libsnap7.so /usr/lib/libsnap7.so
sudo cp ../bin/arm_v6-linux/libsnap7.so /usr/local/lib/libsnap7.so

#install python pip if you don't have it:
sudo apt-get install python-pip
sudo pip install python-snap7

You will need to edit the lib_location on common.py in the /usr/local/lib/python2.7/dist-packages/snap7/ directory
Add a line in the __init__ part of the Snap7Library class:
lib_location='/usr/local/lib/libsnap7.so' 
example below:


class Snap7Library(object):
    """
    Snap7 loader and encapsulator. We make this a singleton to make
    sure the library is loaded only once.
    """
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls)
            cls._instance.lib_location = None
            cls._instance.cdll = None
        return cls._instance

    def __init__(self, lib_location=None):
        lib_location='/usr/local/lib/libsnap7.so' # add this line here
        if self.cdll:
            return
        self.lib_location = lib_location or self.lib_location or find_library('snap7')
        if not self.lib_location:
            msg = "can't find snap7 library. If installed, try running ldconfig"
            raise Snap7Exception(msg)
        self.cdll = cdll.LoadLibrary(self.lib_location)

Now you can write your client code :-)
Here's an example on how to connect and read an output Q0.0:
from time import sleep
import snap7
from snap7.util import *
import struct

plc = snap7.client.Client()
plc.connect("192.168.12.73",0,1)

area = 0x82    # area for Q memory
start = 0      # location we are going to start the read
length = 1     # length in bytes of the read
bit = 0        # which bit in the Q memory byte we are reading

byte = plc.read_area(area,0,start,length)
print "Q0.0:",get_bool(mbyte,0,bit)
plc.disconnect()



I created a helper class on my github here to make the syntax easier for people who are used to DAServer and Ladder:
https://github.com/SimplyAutomationized/raspberrypi/raw/master/S7-1200pi/S71200.py
Example on how to use it:
import S71200
from time import sleep
import snap7
from snap7.util import *
import struct

plc = S71200.S71200("192.168.21.65")
plc.writeMem('QX0.0',True) # write Q0.0 to be true, which will only turn on the output if it isn't connected to any rung in your ladder code
print plc.getMem('MX0.1') # read memory bit M0.1
print plc.getMem('IX0.0') # read input bit I0.0
print plc.getMem("FREAL100") # read real from MD100
print plc.getMem("MW20") # read int word from MW20
print plc.getMem("MB24",254) # write to MB24 the value 254
plc.plc.disconnect()



Let me know if there are questions. Hope I can help :-)
Also let me know if you can help me clean up my S71200.py helper class. I know it looks messy.

Follow me to get updates on a Raspberry pi Sensor the DA or OPC server can get data using S7 protocol.
+Simply Automationized
Check out my other SCADA posts

Tuesday, August 26, 2014

Raspberry Pi, Parse.com, and Temperature Logging



As part of a future project I may be working on(details coming soon). I wanted to get some logging done with some temperature sensors to the online cloud database called Parse.com
If you want your data stored on the cloud to be able to access anywhere this is what you will need to do:
  • install the DS18b20 temperature probes

Parse App Setup

 copy the application id and the rest api key to your python script

Get the ParsePy library:

install on your pi using the command

git clone https://github.com/dgrtwo/ParsePy
cd ParsePy
sudo python setup.py install

Getting my Logging Library:

download here:
https://github.com/SimplyAutomationized/raspberrypi/raw/master/ParseTempLogging/ParseTemperature.py
usage:
from ParseTemperature import *
logger = TempLogger(appkey='yourappkey',apikey='yourapikey')
logger.start()#will create the class in your app and start appending temperature data to it whenever the temperature changes. 

Now the two sensors started populating my online db. 

for reference here's the logging libarary:

from parse_rest.connection import register
from parse_rest.datatypes import Object

from threading import Thread
from time import sleep
import os
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
class Temperature(Object):
 pass


class TempLogger(Thread):
 """
 A class for getting the current temp of a DS18B20
 """
 def __init__(self, fileName='',debug=False,appkey='',apikey=''):
  Thread.__init__(self)
  register(appkey,apikey)#put your api key and app id here
  self.debug = debug
  self.probes = {}
  self.tempDir = '/sys/bus/w1/devices/'
  self.currentTemp = -999
  self.correctionFactor = 1;
  self.enabled = True
  self.repopulateprobes()
 def repopulateprobes(self):
  list = os.listdir(self.tempDir)#here we create a dictionary with the probe id's
  for item in list:
   if(item[:2]=="28"):
   if(self.debug):
    print item
   if(self.probes.has_key(item)==False):
    self.probes[item]=0

 def getTempForFile(self,file):
  try:
   f = open(self.tempDir + file + "/w1_slave", 'r')
  except IOError as e:
   print "Error: File " + self.tempDir + file + "/w1_slave" + " doesn't exist"
   return;
  lines=f.readlines()
  crcLine=lines[0]
  tempLine=lines[1]
  result_list = tempLine.split("=")
  temp = float(result_list[-1])/1000 # temp in Celcius
  temp = temp + self.correctionFactor # correction factor
  #if you want to convert to Celcius, comment this line
  temp = (9.0/5.0)*temp + 32
  if crcLine.find("NO") > -1:
   temp = -999
  if(self.debug):
   print "Current: " + str(temp) + " " + str(file)
  return float(int(temp*100))/100    
 def run(self):
  while self.enabled:
   for item in self.probes.items(): #we iterate through our probes we scanned for earlier and save temperatures to the dictionary
    temp = self.getTempForFile(item[0])
    if(item[1]!=temp):#if there is a change in the temperature we send it to parse
     parseDBObject=Temperature()
     parseDBObject.Probe=item[0]
     parseDBObject.Temperature=temp
     try:
      parseDBObject.save()
     except:
      pass
     self.probes[item[0]]=temp
 def stop(self):
  self.enabled=False
    #returns the current temp for the probe
 def getCurrentTemp(self,file):
  return self.probes[file]