Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java...

73
Blink - Making The World More Accessible, One Blink At A Time Telly Stroumbis The Boeing Company

Transcript of Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java...

Page 1: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Blink - Making The World More Accessible, One Blink At A TimeTelly StroumbisThe Boeing Company

Page 2: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

BIO – Telly StroumbisName: Telly StroumbisKey Technical Field: Software Engineering/ArchitectureE-mail: [email protected]

Telly Stroumbis is a Computer Systems Architect and Technical Fellow for Boeing. He designs and leads Java and Java Enterprise Edition development efforts and provides technical support to numerous Boeing efforts. Telly was an early adopter and has been developing with JavaTM for the last 12 years. For the past 1.5 years, Telly has been working with Volunteers for Medical Engineering in the development of the Blink System. The Blink software is designed to aid those with MS, ALS and other diseases causing weak or paralyzed muscles. The software is designed to help severely paralyzed patients communicate and control their environments.

2

Page 3: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Agenda> Introducing Blink

Background Overview Capabilities

> The Tech Of Blink Plug-in Architecture Text To Speech Swing Hacks Device Control

> Questions3

Page 4: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Introducing Blink> Background> Overview> Capabilities

4

Page 5: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

VME Concept> VME - Volunteers for Medical Engineering> Non-Profit Organization, Incorporated in 1982> Based In Baltimore, Maryland> Goal is to increase the independence of

individuals with disabilities and the elderly through: Custom design of new products Research and development Modifications to existing devices

5

Page 6: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

VME Past Projects

6

*Images courtesy of Volunteers for Medical Engineering

Page 7: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

VME Brown Bag"Almost 20 years ago, Volunteers for Medical Engineering (VME) developed a system to help a disabled man who could only blink to communicate with his family. They designed and built a mechanism and software to create what is now called the Blink System."

"The Blink System operates using a cursor that moves at a selected speed through rows, scanning to the bottom row, then back to the top, and then repeating the process. When the user blinks one eye the cursor stops scanning downward and starts stepping one box at a time across the row. The second blink stops the cursor and the contents of the box are spoken."

"Over time, however, the program controlling the Blink Switch became obsolete. "

7

Page 8: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Modernize Blink> Design for portability> Design for supportability> Design for configurability> Support a variety of input devices> Support speech output> Provide X10, INSTEON, & IR control capabilities> Provide Email & SMS capabilities

8

Page 9: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Portability> Develop using Java> Java code compiles to byte code> Byte code runs in a Java Virtual Machine (JVM)> JVM’s exist for all major platforms> Supports write once run anywhere> Tested On Windows, Linux, Mac OS

9

Page 10: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Supportability> Java is a modern language> Java is strongly typed> Java runs on everything from smart cards & cell

phones to big iron such as eBay and Amazon> JavaOnesm - Java Developers Conference, largest

technical conference (15K – 23K developers)> Java is Object Oriented> Develop using a plug-in architecture (features can

be added without modifying the code base)

10

Page 11: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Configurability> Plug-in based architecture> Capabilities defined in an XML file> New capabilities easily added> User Interface is fully customizable> Customizations saved in an XML file

11

Page 12: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Blink Design

12

Voice• Text To Speech• Volume• Voice

X10• Device On• Device Off• Dimmer

Email• To• Subject• Message

Command• Type• Display Text• Command• Data• Status

Page 13: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Input Devices> Support a wide variety of input devices> System operation using only a mouse> Scanner mode using only a left mouse click> Additional switches and sensors emulate a mouse

device. Examples include:Blink Switch, Sip Puff Switch, Twitch Switch, Bite Switch, Tongue Switch, Head Mouse, etc.

13

*Images courtesy of Origin Instruments Corporation

Page 14: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Text and Speech Output> Supports the capability to display words, phrases,

and sentences on the user display> Supports predictive words and phrases> Supports Text To Speech (TTS)> FreeTTS – An Open Source Java speech

synthesizer

14

Page 15: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Email> Supports communications through email> Supports SMS messaging using an SMS gateway

15

Page 16: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

X10 & INSTEON Control> Supports control of X10 & INSTEON devices> Plug-in talks to an X10/INSTEON Gateway> EZSrve – Control X10 & INSTEON devices over a

network - Price $209.99http://www.smarthome.com/31279.html

16

Page 17: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

IR Control> Supports control of IR devices> Plug-in talks to an IR Gateway> Global Caché – Control IR devices over a network

- Price $159.99http://www.smarthome.com/8114.html

17

Page 18: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Welcome To Blink

18

P rog ra m m a ble K e ys – Y o u c a n

c ha ng e the func t io n, la be l, a nd

a ppe a ra nc e o f the s e ke y s

P ull-do w n Me nus

A re a w he re y o ur te xt a ppe a rs

R e a l-t im e

C lo c k

S ug g e s tio ns – P ro vide s

s ug g e s te d w o rds fo r yo ur

c o m po s e d te xt

T a bs –

Y o u c a n a dd, de le te , a nd

re o rde r ta b s

Quic k A c tio n B a r -

F o r Ofte n Us e d

F unc tio ns

Page 19: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

The Tech Of Blink> Switch Input Hack> Plug-in Architecture> Predictive Text> Text To Speech> Swing Hacks> Device Control

Note: In Code Samples, Error Handling Removed For Brevity

19

Page 20: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Switch Input On The Cheap

20

Page 21: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

PLUG-IN ARCHITECTUREThe Tech Of Blink

21

Page 22: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Plug-in Architecture> All commands handled by plug-ins> Plug-ins bundled Into a jar file> “devices.xml” file configures 1 or more plug-ins> File located at root of jar file> Device entries include:

Commands – Actions to perform Properties – Configuration options Java Class to load

22

Page 23: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Sample Device Entry<device name="JavaSpeech"

class="vme.blink.device.SpeechDevice”> <commands> <command name="SAY" value="SAY"/> </commands> <properties> <property name="VOLUME" value="1.0"/> <property name="PITCH" value="100.0"/> <property name="RATE" value="150.0"/> <property name="VOICE" value="kevin16"/> </properties></device>

23

Page 24: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Finding Plug-ins> public URL getResource(String name)

Finds "the" resource with the given name Searches The Java CLASSPATH Returns The First Match

> public Enumeration<URL> getResources(String name) Finds "all the" resources with the given name

24

Page 25: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Create Hashmap Of Plug-insClassLoader loader = this.getClass().getClassLoader();Enumeration<URL> urls = loader.getResources("devices.xml"); while(urls.hasMoreElements()) {

URL url = urls.nextElement(); InputStream input = url.openStream();Document doc = BlinkImport.getDocument(input); ArrayList<DeviceEntry> deviceList = BlinkImport.getDevices(doc); for(int i=0; i < deviceList.size(); i++) {

DeviceEntry entry = deviceList.get(i);devices.put(entry.getDeviceName(), entry);

}}

25

Page 26: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Device Has A Lifecyclepublic interface Device { public void init(String deviceName, Properties commands, Properties properties); public void start(); public void stop(); public void destroy(); public CommandStatus process(Command command);

}

26

Page 27: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Processing A Command> Find the device> Invoke process() on the command> Plug-in Class gets loaded on demand

Device device = getDevice(command.getDeviceName()); CommandStatus status = device.process(command);

27

Page 28: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Dynamic Class InstantiationDevice device = deviceCache.get(deviceName); if(device == null) {

DeviceEntry entry = config.getDeviceEntry(deviceName); device = (Device)Class.forName(entry.getDeviceClass()).newInstance();

device.init(deviceName, entry.getCommands(), preferences.getDevicePreferences(deviceName));

device.start();deviceCache.put(deviceName, device);

} return device;

28

Page 29: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

PREDICTIVE TEXTThe Tech Of Blink

29

Page 30: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Java DB> Embeddable database> 100% Java> Mature product> Long history

1996 – Cloudscape Inc 1999 – Informix Software, Inc 2001 – IBM 2004 – Apache Derby Java DB Is SUN's supported distribution of Derby

30

Page 31: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Simple Database Startupprivate static final String DB_URL = "jdbc:derby:BlinkDB";private Connection con; public SuggestionDAO (File blinkHome) {

// we want to specify the database locationSystem.setProperty("derby.system.home", blinkHome.getPath());

File dbDir = new File(blinkHome, "BlinkDB");

Class.forName("org.apache.derby.jdbc.EmbeddedDriver");

// Get a connection to the database this.con = DriverManager.getConnection(DB_URL);}

31

Page 32: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Simple Design> Words Table – Contains Words Used & Freq> Phrase Table – Contains Phrases Used & Freq

> Pre-Load With Small List Of Common Words Large Lists Tend To Be Bad Results In Suggestions Of Uncommon Words

> Suggestions Ordered By Frequency> Frequency Updated When Command Issued

32

Page 33: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Word Suggestions> Simple JDBC Query

String sql = "select name from WORDS where name like ? order by freq desc, name asc";

PreparedStatement stmt = con.prepareStatement(sql);

stmt.setString(1, word + "%");

ResultSet rset = stmt.executeQuery();

33

Page 34: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Updating Word Frequency> When Command Issued, Update Word/Phrase

Frequencies

> If Word Exists, Update, Otherwise Insert

String selectSql = "select freq from words where name = ?";

String updateSql = "update WORDS set freq=? where name = ?";String insertSql = "insert into WORDS VALUES (?, 1)";

34

Page 35: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Shutting Down> Always Shutdown A Database When Exiting

Speeds Up Database Startup Database Doesn't Have To Recover

public void shutdown() { try{ con.close(); DriverManager.getConnection(DB_URL + ";shutdown=true"); }catch(Exception e) { // successful shutdown always throws an exception }}

35

Page 36: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

TEXT TO SPEECHThe Tech Of Blink

36

Page 37: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Java Speech API> There Is An Optional Java Speech API> FreeTTS Is An Open Source Implementation> http://freetts.sourceforge.net

> Speech Device Lifecycle We Create & Initialize on init() Resume It on start() Pause It On stop() Deallocate It On destroy()

37

Page 38: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Get The Speech SynthesizerFreeTTSEngineCentral central = new FreeTTSEngineCentral();

SynthesizerModeDesc desc = new SynthesizerModeDesc( null, // engine name "general", // mode name Locale.US, // locale null, // running null); // voice

EngineList list = central.createEngineList(desc);

if (list.size() > 0) { EngineCreate creator = (EngineCreate) list.get(0); synthesizer = (Synthesizer) creator.createEngine();

}

38

Page 39: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Prepare It To Speak

synthesizer.allocate();synthesizer.resume();

39

Page 40: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Find Voice Specified In Properties> Find The First Voice That Matches

desc = (SynthesizerModeDesc) synthesizer.getEngineModeDesc();

Voice[] voices = desc.getVoices();Voice voice = null; for (int i = 0; i < voices.length; i++) {

if (voices[i].getName().equals(voiceName)) {voice = voices[i];break;

}

40

Page 41: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Initialize It With Our Properties> The Importance Of Configurability

An Elderly Care Giver Had Trouble Understanding The Speech The Ability To Slow The Speaking Rate Resolved This

synthesizer.getSynthesizerProperties().setVoice(voice);synthesizer.getSynthesizerProperties().setPitch(pitch);synthesizer.getSynthesizerProperties().setSpeakingRate(rate);synthesizer.getSynthesizerProperties().setVolume(vol);

41

Page 42: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Now We Are Ready To Speak> There Is A Java Speech Markup Language> We Simply Use Plain Text> The Second Argument Is For An Optional Listener

synthesizer.speakPlainText(command.getData(), null);

42

Page 43: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

SWING HACKSThe Tech Of Blink

43

Page 44: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Command Tabs

> Why Create A JTable For Each Tab?

44

> Looks Like A JTable In A JTabbedPane> Looks Can Be Deceiving

tabbedPane = new JTabbedPane(); table = new JTable();tabbedPane.addTab("title", table);

Page 45: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Command Tabs Hack> Create Custom Component> JTable Is Under The TabbedPane> TabbedPane's Component

Simple BlinkTableComponent Has Dimension(0, 0); Contains BlinkTableModel

> Drag & Drop Feature Based On DnDTabbedPane by TERAI Atsuhiro

45

Page 46: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

BlinkTabbedPanepublic BlinkTabbedPane() { pane = new DnDTabbedPane(); pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); pane.addChangeListener(this); table = new JTable(); table.setRowHeight(50); table.setShowGrid(false); table.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0))); setLayout(new BorderLayout()); add(pane, BorderLayout.NORTH); add(table, BorderLayout.CENTER);}

46

Page 47: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

When State Changes, Update JTablepublic void stateChanged(ChangeEvent e) { // Get current tab int sel = pane.getSelectedIndex(); if(sel < 0) return; BlinkTableComponent c = getTableComponentAt(sel); if(c == null) return;

BlinkTableModel model = c.getModel();

table.setModel(model); // in case we have a different number of rows, adjust cell size resized();}

47

Page 48: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

When Resized, Update Row Height table.addComponentListener(new ComponentAdapter(){

public void componentResized(ComponentEvent e) {resized();

} }); public void resized() { int tableHeight = table.getHeight(); int rows = table.getRowCount(); if(rows <= 0) return; int rowHeight = tableHeight / rows; if(rowHeight > 1) { table.setRowHeight(rowHeight); } }

48

Page 49: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

JDK 1.6 Supports For Tab Componentspublic class BlinkTabComponent extends JComponent {

public BlinkTabComponent(String title, BlinkTabbedPane pane) {setLayout(new FlowLayout(FlowLayout.CENTER, 2, 1));

add(tabTitle);add(tabField);add(acceptButton);add(editButton);add(exportButton);add(deleteButton);

}

BlinkTabComponent tab = new BlinkTabComponent(title, this);pane.setTabComponentAt(index, tab);

49

Page 50: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

The Look Of Blink> Ideas Taken From:

"TS-3548 - Extreme GUI Makeover 2007" Chris Campbell, Shannon Hickey, Romain Guy

> Create A Custom Cell Renderer> Set A Custom Border> Override paintComponent()> Gradient Goes From Top Left To Bottom Right> Cycles Once, Darker, Lighter, Darker

50

Page 51: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Rounded Borderprivate class RoundedBorder extends AbstractBorder {

private final Color FILL = new Color(135, 135, 135);private final Stroke STROKE = new BasicStroke(2f);

public void paintBorder(Component c, Graphics g,

int x, int y, int width, int height) { Graphics2D g2 = (Graphics2D)g.create(); g2.setRenderingHint(

RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

g2.setColor(FILL); g2.setStroke(STROKE); g2.drawRoundRect(4, 4, width-8, height-8, 10, 10);

g2.dispose();}

}

51

Page 52: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Paint Cell With Gradientpublic void paintComponent(Graphics graphic) {

Graphics2D g2 = (Graphics2D)graphic;g2.setRenderingHint(…);int width = getWidth();int height = getHeight();

Color startColor = getBackground();Color[] colors = ColorRange.getLighter(startColor, 0.15f);startColor = colors[0]; Color endColor = colors[1];

Paint bg = new GradientPaint(0f, 0f, startColor, getWidth()/2, getHeight()/2, endColor, true);

g2.setColor(Color.WHITE);g2.fillRoundRect(4, 4, width-8, height-8, 10, 10);g2.setPaint(bg);

g2.fillRoundRect(7, 7, width-11, height-11, 10, 10);}

52

Rounded Border

Fill White

Fill Gradient

Page 53: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

DEVICE CONTROLThe Tech Of Blink

53

Page 54: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Device Control Challenges> Avoid OS specific device drivers> Don't want to tether user> Solution: Network Gateways

Gateway for INSTEON/X10 Gateway for IR Future: Maybe OpenRemote.Org

One device for both Complexity follows SEP principal

54

Page 55: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

EZSrve Gateway> Standalone INSTEON & X10 Controller> Web Based GUI On Port 80> XML Interface On port 8002

We Can Control INSTEON & X10 Devices By Sending XML Messages On port 8002

<Command> Command Name<Parameter 1> Value </Parameter 1><Parameter 2> Value </Parameter 2><Parameter ….> Value </Parameter ….>

</Command>

55

Page 56: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

INSTEON Commands> Each Module Has A Unique Address> Flags Allow Us To Specify How Many Hops> Some Commands Use 2 Parameters

ON Command has brightness level

<command>SndIns<parameter1>to id high byte</parameter1><parameter2> to id middle byte </parameter2><parameter3> to id low byte </parameter3><parameter4>flags</parameter4><parameter5>Command1</parameter5><parameter6>Command2</parameter6>

</command>56

Page 57: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Formatting An INSTEON Commandprivate static String INS_CMD = "<command>SndIns" + "<parameter1>0x{0}</parameter1>" + "<parameter2>0x{1}</parameter2>" + "<parameter3>0x{2}</parameter3>" + "<parameter4>0x{3}</parameter4>" + "<parameter5>0x{4}</parameter5>" + "<parameter6>0x{5}</parameter6></command>";

String[] insAddr = addr.split("\\."); String flag = "0F";String cmd2 = "00";if(command == INSCommand.ON) cmd2 = "FF";

String cmd = MessageFormat.format(INS_CMD, insAddr[0], insAddr[1],insAddr[2], flag, command.getValue(), cmd2);

57

Page 58: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

X10 Commands> Module has a 2 part Selectable Address

House code: A-P Unit code: 1-16 4 most sig bits house code, 4 least sig bits unit code

> Action often requires two X10 Commands Select the unit (has flag: 0x00) Issue the command (has flag: 0x80)

> Command Always Issued To House Code<command>SndX10

<Parameter1> rawX10</Parameter1><Parameter2> X10Flag </Parameter2>

</command>58

Page 59: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Translation Tables Determine What's SentProperties x10HouseCodes = new Properties() { { setProperty("A", "6"); setProperty("B", "E"); setProperty("C", "2"); setProperty("D", "A"); setProperty("E", "1"); setProperty("F", "9"); setProperty("G", "5"); setProperty("H", "D"); setProperty("I", "7"); setProperty("J", "F"); setProperty("K", "3"); setProperty("L", "B"); setProperty("M", "0"); setProperty("N", "8"); setProperty("O", "4"); setProperty("P", "C"); } };

Properties x10UnitCodes = new Properties() { { setProperty("1", "6"); setProperty("2", "E"); setProperty("3", "2"); setProperty("4", "A"); setProperty("5", "1"); setProperty("6", "9"); setProperty("7", "5"); setProperty("8", "D"); setProperty("9", "7"); setProperty("10", "F"); setProperty("11", "3"); setProperty("12", "B"); setProperty("13", "0"); setProperty("14", "8"); setProperty("15", "4"); setProperty("16", "C"); } };

59

Page 60: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Formatting An X10 Commandprivate static String X10_SELECT = "<command>SndX10" + "<Parameter1>0x{0}{1}</Parameter1>" + "<Parameter2>0x00</Parameter2></command>"; private static String X10_CMD = "<command>SndX10" + "<Parameter1>0x{0}{1}</Parameter1>" + "<Parameter2>0x80</Parameter2></command>";

String house = x10HouseCodes.getProperty(houseCode);String unit = x10UnitCodes.getProperty(unitCode);

String sel = MessageFormat.format(X10_SELECT, house, unit);String cmd = MessageFormat.format(X10_CMD, house, command.getValue());

60

Page 61: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Sending Messages> Open A Socket> Write The Command> Read The Results> We Need To Add A Delay Between Commands

I'm using 800ms

socket = new Socket(address, port);out = socket.getOutputStream();in = socket.getInputStream();

out.write(xml.getBytes());out.flush();

61

Page 62: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

IR Primer> IR light source

Alternates on/off Rate: Carrier frequency

> Encodings determine Mixture of on/off states Cycles on/off Duration on/off

> Multiple encodings Pulse Width (80% est.) Bi-Phase (RC-5)

62

1 2 3 4 5 6 7 8

40,000 Hz4 Cycles On, 4 Cycles Off1/40,000 Hz = 0.025 ms0.1 ms On, 0.1 ms Off

Page 63: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Pulse Width Encoding> Consists of on/off Pairs> Data encoded by varying on/off durations> Data often consists of

Lead-in data IR command data Lead-out data

63

Page 64: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Encoding Formats> Pronto Hex Format

Popular format for the Phillips Pronto Remotes http://www.remotecentral.com/

> LIRC Format Linux Infrared Remote Control http://www.lirc.org/

64

Page 65: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Pronto Hex Format> Series of hex values> First 4 words represent preamble> Followed by on/off durations in cycles> Sample preamble = 0000 0067 000 0015

0000 – Learned Code 0067 – 40,000 Hz freq (relative to pronto freq) 0000 – Length one-time burst (none exists) 0015 – Length of repeat burst (21 Pairs/42 Words)

Note: Frequency = 1000000/(N * .241246)Reference: http://www.hifi-remote.com/infrared/

65

Page 66: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

LIRC Format> Set of instructions for generating data

Default freq 38,000 Hz, Timings in microsecondsbegin remote

 name  DVD  bits            7  flags SPACE_ENC|CONST_LENGTH  header     2400   600  one          1200   600  zero          600   600  ptrail        600  post_data_bits  12  post_data      0x5C9  gap          44749  min_repeat      3 begin codes

power_on                 0x3A

66

Page 67: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Converting LIRC To ProntoFreq = 38,000Cycle = 1,000,000 * (1/38,000) = 26 usec

600 usec off = 600 / 26 = 23 cycles or 0x17

header:     2400   600 = 005c 0017zero: 600 600 = 0017 0017one: 1200 600 = 002e 0017

power_on: 0x3A = 7 bits: 0111010 0 1 1 1 0 …0017 0017 002e 0017 002e 0017 002e 0017 0017 0017 ...

Add post data & gap67

Page 68: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

These Sequences Look DifferentSample Used Freq = 40,000 Hz – LIRC Used Freq 38,000 Hz (10% tolerance OK)

Pronto Hex Sample:0000 0067 0000 0015 0060 0018 0018 0018 0030 0018 0030 0018 0030 0018 0018 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 0018 0030 0018 0030 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 03f6

LIRC Conversion To Pronto Hex:0000 006d 0000 0015 005c 0017 0017 0017 002e 0017 002e 0017 002e 0017 0017 0017 002e 0017 0017 0017 0017 0017 002e 0017 0017 0017 002e 0017 002e 0017 002e 0017 0017 0017 0017 0017 002e 0017 0017 0017 0017 0017 002e 0017 0017 06b9

68

Page 69: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Adjusting LIRC For Freq 40,000 HzLIRC specifies longer trailing gap – do nothing before next command

Pronto Hex Sample:0000 0067 0000 0015 0060 0018 0018 0018 0030 0018 0030 0018 0030 0018 0018 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 0018 0030 0018 0030 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 03f6

LIRC Conversion To Pronto Hex:0000 0067 0000 0015 0060 0018 0018 0018 0030 0018 0030 0018 0030 0018 0018 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 0018 0030 0018 0030 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 06fe

69

Page 70: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Global Caché IR Gateway> Data sent on port 4998> Command sent in ASCII text> Command terminated by a carriage return> On/Off values are in cycles of carrier frequency

How many cycles on How many cycles off Like Pronto Hex, but values in decimal and comma

separated

sendir,<connectoraddress>,<ID>,<frequency>,<count>,<offset>,<on1>, <off1>,<on2>,<off2>,….,onN,offN

String cmd = "sendir,2:1,1," + code.getGCCode() + "\r";

70

Page 71: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

Status> Software is free> Distributed under GPLv3 license> Currently in alpha testing

71

Page 72: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

72

Questions?

Page 73: Making The World More Accessible, One Blink At A Time - Oracle€¦ · > Develop using Java > Java code compiles to byte code > Byte code runs in a Java Virtual Machine (JVM) > JVM’s

73

Telly [email protected]@blinksystem.comhttp://blinksystem.com