In my last project I solved a big issue that I needed to receive notification from an hardware via a Multicast UDP socket.
If you want to know more about Multicast and Unicast in Flash Platform I really suggest to read Flashrealtime blog.
Like you know the Flash Platform can use multicast with RTMFP protocol so you can use it Flash to Flash or Flash to Flash Media Server but not Flash to hardware for example.
In my case I needed a Multicast UDP socket in a local application that communicate with an hardware that was my server, so I thought to realize a Python application for Mac OS X and Windows that could help me to solve this problem.
Python is my second favorite programming language after ActionScript (obviously) and this time Python saves me to accomplish my project.
I want to start with Python side, my goal is to connect to a multicast socket and get all data and then send them to a unicast UDP socket server that we will create in Adobe AIR in next example.
#!/usr/bin/env python
# encoding: utf-8
import socket, select
ANY = '0.0.0.0'
MCAST_ADDR = '239.0.1.1'
MCAST_PORT = 10300
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sock.bind((ANY,MCAST_PORT))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
status = sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY));
sock.setblocking(0)
print 'socket UDP multicast ready'
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
while 1:
ins, outs, errs = select.select( [ sock ] , [], [], 1.0)
try:
data, addr = sock.recvfrom(1024)
except socket.error, e:
pass
else:
print data
udp.sendto(data, (socket.gethostbyname('127.0.0.1'), 10303))
socket.close()
First few lines we define the multicast socket server ip (that in my case is pointing to the hardware) and the socket port to communicate with.
Then I create the UDP multicast socket and the UDP unicast socket (udp var); in the while loop I set the socket timeout and if I receive data trough the multicast socket I send everything to unicast one.
After that to create an application without any dependency in Windows or Mac OS X, you need to use a couple of Python libraries called py2app and py2exe.
Both allow you to create an executable file from your Python script for mac or win without any dependencies, in Windows side you have only to remember which kind of Python dll you have to incapsulate in your AIR application but we take a look at that in a while.
To create the executable file you have to create a setup script in Python for both operating systems, I suggest to create something like that:
FOR WINDOWS:
from distutils.core import setup
import py2exe,sys,os
origIsSystemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(pathname):
if os.path.basename(pathname).lower() in ("msvcp71.dll", "dwmapi.dll"):
return 0
return origIsSystemDLL(pathname)
py2exe.build_exe.isSystemDLL = isSystemDLL
setup(windows=['myPythonScript.py'])
FOR MAC:
from setuptools import setup
APP = ['myPythonScript.py']
DATA_FILES = []
OPTIONS = {'argv_emulation': True}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
Then if you want to create your executable files you have only need to launch the command on command prompt or terminal (you can find more informations on how to customize those setup scripts in each library’s website):
FOR WINDOWS:
python setup.py py2exe
FOR MAC:
python setup.py py2app
Now we can start with the AIR part, like you know with AIR 2 you can work with Native Process and this is the case to use them:
const WIN_PATH:String = "win/socket.exe";
const OSX_PATH:String = "socket.app/Contents/MacOS/socket";
var nativep:NativeProcessStartupInfo = new NativeProcessStartupInfo();
var finalPath:String;
var f:File
if(Capabilities.os.substr(0, 3) == "Win"){
finalPath = WIN_PATH
}else{
finalPath = OSX_PATH
}
f = File.applicationDirectory.resolvePath(finalPath);
nativep.executable = f;
var process:NativeProcess = new NativeProcess();
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
process.addEventListener(NativeProcessExitEvent.EXIT, onExit);
process.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onIOError);
process.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOError);
process.start(nativep);
var udp:DatagramSocket = new DatagramSocket();
udp.addEventListener(DatagramSocketDataEvent.DATA, getData);
udp.bind(10303);
udp.receive();
function getData(e:DatagramSocketDataEvent):void{
trace(">>>>>" + e.data.readUTFBytes( e.data.bytesAvailable ))
}
function onOutputData(event:ProgressEvent):void{
trace(process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable));
}
function onErrorData(event:ProgressEvent):void{
trace(process.standardError.readUTFBytes(process.standardError.bytesAvailable));
}
function onExit(event:NativeProcessExitEvent):void{
trace(event.exitCode);
}
function onIOError(event:IOErrorEvent):void{
trace(event.toString());
}
In this simple script I’m choosing the right executable file for the operating system where my AIR application is working on and then I launch the native process to start the multicast socket.
Finally I listen for the unicast socket and I trace on the output panel the messages that I receive from the hardware.
I think this is an interesting way to extend Adobe AIR with Python that open new possibilities on the desktop side, think for example to create a Python bluetooth extension for Adobe AIR, it could be so interesting add this feature to AIR apps isn’t it?
Like this:
Like Loading...