# HG changeset patch # User drewp # Date 1330861348 28800 # Node ID a422d875d94dfc986de0b7075a063117451c43cd # Parent f97547561b1dbef1e76fff51bd02df8126919d9b barcode support on star. triggers mpd song Ignore-this: 1038c3d0501bba595fbf701e30acac6 darcs-hash:20120304114228-312f9-8fc9a9198be2044359f35aebcd1c428a58cb4ea2.gz diff -r f97547561b1d -r a422d875d94d service/starArduino/barcodePlayer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/starArduino/barcodePlayer.py Sun Mar 04 03:42:28 2012 -0800 @@ -0,0 +1,42 @@ +#!bin/python +""" +receives POSTs about barcodes that are scanned, plays songs on mpd +""" + +from __future__ import division + +import cyclone.web, cyclone.httpclient, sys, json +from twisted.python import log +from twisted.internet import reactor +from twisted.internet.defer import inlineCallbacks +sys.path.append("/my/proj/homeauto/lib") +from cycloneerr import PrettyErrorHandler + + + +class Index(PrettyErrorHandler, cyclone.web.RequestHandler): + def get(self): + + self.set_header("Content-Type", "application/xhtml+xml") + self.write(open("index.html").read()) + +class BarcodeScan(PrettyErrorHandler, cyclone.web.RequestHandler): + @inlineCallbacks + def post(self): + print json.loads(self.request.body) + + song = "cd/Kindermusik-The_Best_of_the_Best/14.Fiddle-de-dee.ogg" + + print (yield cyclone.httpclient.fetch(url="http://star:9009/addAndPlay/%s" % song, method="POST")).body + + self.write("ok") + + +if __name__ == '__main__': + app = cyclone.web.Application([ + (r'/', Index), + (r'/barcodeScan', BarcodeScan), + ], ) + log.startLogging(sys.stdout) + reactor.listenTCP(9011, app) + reactor.run() diff -r f97547561b1d -r a422d875d94d service/starArduino/star/star.pde --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/starArduino/star/star.pde Sun Mar 04 03:42:28 2012 -0800 @@ -0,0 +1,241 @@ +/* +board is like diecimila with atmega168 + +*/ +#include +int datapin = 10; // DI +int latchpin = 11; // LI +int enablepin = 12; // EI +int clockpin = 13; // CI + +unsigned long SB_CommandPacket; +int SB_CommandMode; +int SB_BlueCommand; +int SB_RedCommand; +int SB_GreenCommand; + +#define MAXCHANS 16 +int vals[MAXCHANS * 3]; + +int addr = 0; // which vals element to set next +int currentChans = MAXCHANS; + +unsigned char rotation = 0; // position of knob +unsigned char lastRotPosition = 0; // 2*A+1*B + +#define TEMP_ENABLED 1 + +#if TEMP_ENABLED +#include +#include + +OneWire oneWire(4); // digital IO 4 +DallasTemperature sensors(&oneWire); +DeviceAddress tempSensorAddress; +#endif + +/* +barcode red: +5V +barcode white: gnd + */ +SoftwareSerial barcode = SoftwareSerial(/* rx pin, green */ 3, + /* tx pin, black */ 2, + /* inverse */ true); + +void shiftOutLocal(uint8_t dataPin, uint8_t clockPin, byte val) +{ + int i; + + for (i = 0; i < 8; i++) { + digitalWrite(dataPin, !!(val & (1 << (7 - i)))); + + digitalWrite(clockPin, HIGH); + digitalWrite(clockPin, LOW); + } +} + +void SB_SendPacket() { + SB_CommandPacket = SB_CommandMode & B11; + SB_CommandPacket = (SB_CommandPacket << 10) | (SB_BlueCommand & 1023); + SB_CommandPacket = (SB_CommandPacket << 10) | (SB_RedCommand & 1023); + SB_CommandPacket = (SB_CommandPacket << 10) | (SB_GreenCommand & 1023); + + shiftOutLocal(datapin, clockpin, SB_CommandPacket >> 24); + shiftOutLocal(datapin, clockpin, SB_CommandPacket >> 16); + shiftOutLocal(datapin, clockpin, SB_CommandPacket >> 8); + shiftOutLocal(datapin, clockpin, SB_CommandPacket); + +} +void latch() { + delayMicroseconds(100); + digitalWrite(latchpin,HIGH); // latch data into registers + delayMicroseconds(100); + digitalWrite(latchpin,LOW); +} +void refresh() { + /* send all pixels */ + SB_CommandMode = B00; + for (int pixel=0; pixel < currentChans; pixel++) { + SB_RedCommand = vals[pixel * 3 + 0]; + SB_GreenCommand = vals[pixel * 3 + 1]; + SB_BlueCommand = vals[pixel * 3 + 2]; + SB_SendPacket(); + } + latch(); +} +#define F 1023 +#define PIXEL(i, r, g, b) { vals[i*3+0] = r; vals[i*3+1] = g; vals[i*3+2] = b; } + +void setCurrent(unsigned char r, unsigned char g, unsigned char b) { + /* 127 = max */ + SB_CommandMode = B01; // Write to current control registers + SB_RedCommand = r; + SB_GreenCommand = g; + SB_BlueCommand = b; + SB_SendPacket(); + latch(); +} +void setup() { + pinMode(datapin, OUTPUT); + pinMode(latchpin, OUTPUT); + pinMode(enablepin, OUTPUT); + pinMode(clockpin, OUTPUT); + + digitalWrite(latchpin, LOW); + digitalWrite(enablepin, LOW); + + for (int i=0; i < MAXCHANS; i++) { + setCurrent(127, 127, 127); + } + + PIXEL(0, F, 0, 0); + PIXEL(1, 0, F, 0); + PIXEL(2, 0, 0, F); + PIXEL(3, F, F, 0); + PIXEL(4, 0, F, F); + refresh(); + +#if TEMP_ENABLED + sensors.begin(); + sensors.getAddress(tempSensorAddress, 0); + sensors.setResolution(tempSensorAddress, 12); +#endif + + Serial.begin(9600); + Serial.flush(); + + pinMode(5, INPUT); + pinMode(6, INPUT); + pinMode(7, INPUT); + pinMode(8, INPUT); + pinMode(9, INPUT); + digitalWrite(6, HIGH); + digitalWrite(8, HIGH); + digitalWrite(9, HIGH); + + + barcode.begin(1200); + digitalWrite(2, 0); // inverse logic: don't hold this high + + /* + barcode.write("\x1b\x42\x0d"); // blink + */ + /* + barcode.write("\x1b\x46\x0d"); // off + */ +} + +void loop() { + /* + send 0xff, + then a byte for the number of channels you're going to send, + then nchans*3 bytes of r-g-b levels from 0x00-0xfe. + + second byte 0xfe means to return temp in F, followed by \n + second byte 0xfd means to return a line describing the state of buttons + second byte 0xfc means to beep the barcode scanner + second byte 0xfb means to fetch any recent scanned barcode + */ + + unsigned char curPos = (digitalRead(8) << 1) | digitalRead(9); + + if (curPos == 0 && lastRotPosition == 2) { rotation--; } + if (curPos == 0 && lastRotPosition == 1) { rotation++; } + if (curPos == 1 && lastRotPosition == 0) { rotation--; } + if (curPos == 1 && lastRotPosition == 3) { rotation++; } + if (curPos == 3 && lastRotPosition == 1) { rotation--; } + if (curPos == 3 && lastRotPosition == 2) { rotation++; } + if (curPos == 2 && lastRotPosition == 3) { rotation--; } + if (curPos == 2 && lastRotPosition == 0) { rotation++; } + + lastRotPosition = curPos; + + int inb = Serial.read(); + if (inb == -1) { + return; + } + if (inb == 0xff) { + addr = -1; + return; + } + if (addr == -1) { + if (inb == 0xfe) { +#if TEMP_ENABLED + sensors.requestTemperatures(); + float tempF = sensors.getTempF(tempSensorAddress); + Serial.print(tempF); + Serial.print("\n"); +#endif + addr = -1; + return; + } + if (inb == 0xfb) { + if (barcode.available() < 1) { + Serial.print("{\"barcode\":\"\"}\n"); + } else { + Serial.print("{\"barcode\":\""); + char last=1; + while (barcode.available() > 0) { + last = barcode.read(); + Serial.print((int)last); + Serial.print(" "); + } + Serial.print("\"}\n"); + } + return; + } + if (inb == 0xfc) { + barcode.write("\x1b\x54\x0d");// beep + barcode.write("\x1b\x3f\x0d"); // requisition + Serial.print("{\"ok\":1}\n"); + } + + if (inb == 0xfd) { + // read ariremote buttons, where some buttons are combined on + // the same pins + digitalWrite(5, HIGH); Serial.print(digitalRead(5)); + Serial.print(" "); + digitalWrite(5, LOW); Serial.print(!digitalRead(5)); + Serial.print(" "); + digitalWrite(7, HIGH); Serial.print(digitalRead(7)); + Serial.print(" "); + digitalWrite(7, LOW); Serial.print(!digitalRead(7)); + Serial.print(" "); + Serial.print(!digitalRead(6)); + Serial.print(" "); + Serial.print((int)rotation); + Serial.print("\n"); + } + currentChans = inb; + addr = 0; + return; + } + + vals[addr] = inb * 4; // SB levels are 10-bit. log scale might be better + addr ++; + if (addr >= currentChans * 3) { + refresh(); + addr = 0; + } + +} diff -r f97547561b1d -r a422d875d94d service/starArduino/starArduino.py --- a/service/starArduino/starArduino.py Sun Mar 04 03:41:33 2012 -0800 +++ b/service/starArduino/starArduino.py Sun Mar 04 03:42:28 2012 -0800 @@ -6,7 +6,8 @@ import sys, jsonlib from twisted.internet import reactor, task -import cyclone.web +from twisted.internet.task import LoopingCall +import cyclone.web, restkit sys.path.append("/my/proj/pixel/shiftweb") from drvarduino import ShiftbriteArduino @@ -45,22 +46,91 @@ self.set_header("Content-Type", "text/plain") self.write("updated %r" % colors) +class Barcode(PrettyErrorHandler, cyclone.web.RequestHandler): + def get(self): + self.set_header("Content-Type", "text/plain") + ser = self.settings.arduino.ser + ser.write("\x60\x02") + self.write(str(ser.readJson())) + +class BarcodeBeep(PrettyErrorHandler, cyclone.web.RequestHandler): + def put(self): + self.set_header("Content-Type", "text/plain") + ser = self.settings.arduino.ser + ser.write("\x60\x03") + self.write(str(ser.readJson())) + +def barcodeWatch(arduino, postBarcode): + try: + arduino.ser.write("\xff\xfb") + ret = arduino.readJson() + if ret['barcode']: + if ret['barcode'] == "27 80 48 13 ": + pass # scanner's beep response + else: + arduino.ser.write("\xff\xfc") + arduino.readJson() # my beep response + s = ''.join(chr(int(x)) for x in ret['barcode'].split()) + for code in s.split('\x02'): + if not code: + continue + if not code.endswith('\x03'): + print "couldn't read %r" % code + return + codeType = {'A':'UPC-A', + 'B':'JAN-8', + 'E':'UPC-E', + 'N':'NW-7', + 'C':'CODE39', + 'I':'ITF', + 'K':'CODE128', + }[code[0]] + code = code[1:-1] + postBarcode.post(payload=jsonlib.dumps( + {'barcodeType':codeType, 'code':code}), + headers={"content-type" : + "application/json"}) + + except ValueError, e: + print "err", e + + class Graph(PrettyErrorHandler, cyclone.web.RequestHandler): def get(self): raise NotImplementedError if __name__ == '__main__': - sb = ShiftbriteArduino(numChannels=3) + class A(ShiftbriteArduino): + # from loggingserial.py + def readJson(self): + line = '' + while True: + c = self.ser.read(1) + #print "gotchar", repr(c) + if c: + line += c + if c == "\n": + break + else: + raise ValueError("timed out waiting for chars") + return jsonlib.loads(line) + + sb = A(numChannels=3) colors = [(0,0,0)] * sb.numChannels aw = ArduinoWatcher(sb) task.LoopingCall(aw.poll).start(1.0/20) + + postBarcode = restkit.Resource('http://star:9011/barcodeScan') + task.LoopingCall(barcodeWatch, sb, postBarcode).start(interval=.5) reactor.listenTCP(9014, cyclone.web.Application([ (r'/', Index), (r'/temperature', Temperature), (r'/brite/(\d+)', Brite), + (r'/barcode', Barcode), + (r'/barcode/beep', BarcodeBeep), (r'/graph', Graph), ], arduino=sb, colors=colors)) reactor.run()