Category Archives: Tools

How to use a Netgear Nighthawk R7000 with Vodafone NZ fibre

After Chorus connects your fibre optical router to the wifi modem that Vodafone provides, and ensures it’s working, you can switch to using your own, better Nighthawk modem this way:

  1. Detach the red plug from Vodafone’s modem and plug it into the Internet port on the Nighthawk
  2. Follow the instructions in your Nighthawk manual and connecting power, etc.
  3. In a browser, visit routerlogin.net (This is an address that the Nighthawk interprets as referring to itself; it’s not a machine on the Internet, so it will work if the modem is on but you don’t have an Internet connection yet.)
    1. If you can’t connect, follow the instructions about using an Ethernet cable to connect your computer to the Nighthawk
    2. The default login is admin with password password. But if you have house-sitters, you probably want to change this. I recommend using LastPass to keep track of passwords.
    3. If prompted whether to use the Netgear Genie software or a wizard to connect to the Internet, answer yes.
  4. In Genie:
    1. To connect to the Internet:
      1. Select: Advanced / VLAN-Bridge settings / Enable VLAN / Enable VLAN tag / VLAN ID = 10 / click Apply
      2. Note that if you ever use a paperclip to press the recessed reset button, you will need to do the step above to reconnect.
      3. I got this tip from https://community.vodafone.co.nz/t5/Broadband-services/Trying-to-connect-a-new-router-to-the-ONT/td-p/183755
    2. To change the wifi name or password:
      1. Select: Advanced / Setup / Wireless setup / 2.4GHz name ssid = NETWORK NAME YOU WANT / security = wpa2-psk / password = PASSWORD YOU WANT Then do the same for 5GHz but add something like -5G to the name. Click Apply to restart router.
      2. Note that this changes the name of your wifi as it appears on your computer and for any of your guests. It doesn’t change the name and password that you use to access the modem’s settings. If you’ll have a house-sitter that you want to prevent from changing modem settings, follow the steps below.
    3. To change the password for modem settings:
      1. Select: Advanced / Administration / Set Password
      2. Enter password as Old Password
      3. Use LastPass to generate and record a New Password. I recommend saving this to a folder in LastPass that you’ve shared with any other household members that might need to access settings.
      4. NetGear recently advised against using the Enable Password Recovery checkbox for security reasons. If you do lose your password, press the recessed Reset button and redo all of the steps on this page.
      5. Click Apply
      6. When prompted to login again, enter admin as the user and get the password out of LastPass
    4. To set the clock to NZ (which is necessary if you’re going to use a schedule below, but probably not important otherwise):
      1. Select: Advanced / Security / Schedule / Timezone = NZ GMT+12. Adjust for DST = on. Click Apply to restart router.
    5. To turn wifi on and off according to a schedule:
      1. Select: Advanced / Advanced setup / Wireless settings / Wireless advanced settings for 2.4GHz / Turn off by schedule = on / Add new period / start=11pm end=7am daily / click Apply. Then do the same for 5GHz. Click Apply to restart router.
      2. You might need to set both “Turn off by schedule = on” again after updating the schedules.
    6. Logout of Genie and close the browser tab it was in.
  5. Disconnect any Ethernet cable.
Print Friendly, PDF & Email

How to setup Android tablets for offline Amazon video and browser whitelisted parental control

These instructions are for Android 4.4 on two Lenovo TAB 2 tablets bought in the US. I’m also using a 32 GB microSDHC card for each so we can download more.

Aims

  • Allow videos that were bought for watching on Amazon’s website to be watchable while offline (e.g. on a plane)
    • Caveat: There is no option in this app to password-protect all sections other than Downloads in order to keep children from watching trailers and such. There are parental controls that can be enabled, and we did, but this leaves the choice of what’s appropriate to Amazon’s editors.
  • Allow children to access websites that we choose and no others
    • Caveat: We installed an app named Kiosk Browser to do this, but it’s not perfect. Mostly, it’s designed to be the only app that non-admin users of the tablet will be able to use, while we want to allow access to Amazon Video also. Also, if you use the hardware power button while Kiosk Browser is running, which should be a normal thing to do, after startup Android will prompt which launcher app you want to use instead of remembering if you don’t want it to be Kiosk Browser (so that your kids can get to Amazon Video easily)
    • We just learned of Android Chrome’s support for Supervised Users, and this might be a better solution
  • Disable access to all installed apps, including Settings and Play Store, except for Amazon Video, a browser, and maybe Skype for calling relatives
    • Caveat: As of the end of 2015, neither Android Settings nor the Android Play Store offer a way to set a password for access to them specifically, and I could not find any app that I would trust to do this. So this aim isn’t solved yet.
  • Prevent anyone but us parents from changing any of these settings

Steps for offline Amazon Video

  1. Create a Google account to be used only for the children’s apps.
  2. Enable 2-factor auth on that Google account, which should help prevent your child from installing anything. To be sure you can get these codes while on a flight, install the Authy app on your phone and use it to photo the QR code shown when you enable two-factor auth.
  3. On each tablet, go into Google Play app and login.
  4. We have a tablet for each child, so to identify the devices, we bought color-coded cases. And went into Play Store using desktop browser > Gear button > Android Device Manager > Pencil button > (added case color to name)
  5. In the tablet Android Settings, disable location services so Google and perhaps others cannot track your child
  6. Disable loud sounds https://forums.lenovo.com/t5/Lenovo-Android-based-Tablets/Start-up-sound-idea-s6000/m-p/1298239#M13520
  7. Make sdhc the default storage medium so you can download more: Android Settings > Storage > SD Card.
  8. Uninstall or disable as many apps as you can except the Play Store and Android Settings (and maybe Skype for calling relatives)
  9. (Necessary only for non-Amazon Fire devices) Using your tablet’s browser, go to https://www.amazon.com/appstore_android_app which will download the Amazon App Store app for Android. Use it to install both Amazon For Tablets app and Amazon Video app (exactly as spelled here, not Instant Video).
  10. Amazon Video app shows “We’re unable to show this content. Please try again later.” I see this while outside the US, so I installed the Android solution of my vpn service https://play.google.com/store/apps/details?id=com.privateinternetaccess.android&hl=en then while connected through it, Android Settings > Apps > Amazon Video > Clear Data.
  11. Logout of Amazon For Tablets, then log back in. Visit ‘Your Orders’ and confirm that it shows actual orders you’ve made — before logout it may show Recently Viewed Items, which indicates it’s confused. You should still be on VPN.
  12. Start Amazon Video and verify your video library is accessible through the menu. Download all your purchases that you want while offline.
  13. After downloading, we could view all the downloads without the vpn and without any network connection at all.
  14. Set Amazon Video app’s parental controls http://www.amazon.com/gp/help/customer/display.html?nodeId=201423060

Setting up a browser that enforces a whitelist

  1. Using laptop browser logged into same Google account as the tablet’s Play Store, installed Pro version of https://play.google.com/store/apps/details?id=com.procoit.kioskbrowser because it’s a browser app that has a url whitelist, and is based in a country I trust (UK)
  2. Signup for free trial of the remote management service at https://www.kbremote.net/Home/Start Then in the app go to Settings > Remote Management > Login/Signup > Login and use the same userId and password. In a few minutes, logging into the site will show the device.
  3. Setup which urls should be allowed https://kioskbrowser.userecho.com/topic/908050-profiles/
  4. To make one device’s profile slightly different from others (e.g. different default url), use Profile Overrides https://kioskbrowser.userecho.com/topic/847081-profile-overrides/
    Sign up for a Kiosk Browser forum account at https://kioskbrowser.userecho.com/

Working all this out took me a day and half, so I hope sharing it here saves some other parents some time to prep for their travel!

Print Friendly, PDF & Email

Developing speech applications

Contents

Personal background

The idea of controlling technology by telling it what to do has been compelling for a long time. In fact, when I was part of a “voice portal” startup in 1999-2001 (Quack.com, which rolled into AOLbyPhone 2001-2004 or so), there was a joking acknowledgement that the tech press announces “speech recognition is ready for wide use” about every ten years, like clockwork. Our startup launched around the third such crest of press optimism. And like movies on similar topics that release the same summer, there was a new crop of voice portal startups at the time (e.g., TellMe and BeVocal). Like the browser wars of a few years earlier between Netscape and IE, in which they’d pull pranks like sneaking their logo statue into the competitor’s office yard, we spiked TellMe car antennas with rubber ducks in their parking lot. Those were crazy, fun days when the corner of University and Bryant in Palo Alto seemed like the center of the universe, long hours in our little office felt like a voyage on a Generation Ship, and pet food was bought online. And a little more than a decade later, Apple has bought Siri to do something similar, and Google and Microsoft have followed.

The idea that led to our startup was wanting to help people compare prices with other stores while viewing products at a brick-and-mortar store. Mobile phones then had poor cameras and browsers, so the most feasible interaction method was to verbally select a product type, brand, and model by first calling an Interactive Voice Response (IVR) service. But a web startup needs more traffic than once-a-week shopping, so other services were added such as movie showtimes, sports scores, stock quotes, news headlines, email reading and composing (via audio recording), and even restaurant reviews. This was before VoiceXML reached v1.0 and we used a proprietary xml variant developed in-house alongside our Microsoft C++-based servers. We were the first voice portal to launch in the US, and that was with all services except the price comparison feature that was our initial motivation. It hasn’t reappeared on any voice portal since, that I know of.

As any developer knows, building on standards often provides many advantages. Once VXML 1.0 appeared, I wanted to see if we could migrate to it, so I bought a Macintosh G4 with OS X v1 when the Apple store first opened in Palo Alto, and used the Java “jar” wrappers for its speech recognition and generation features to prototype a vxml “browser”. When it supported 40% of the vxml spec, I shared it with our startup, recently bought by AOL, but they passed. I stopped work on it and released it as open-source through the Mozilla Foundation (see vbrowse.mozdev.org).

More than a decade later, markup-based solutions like vxml still seem like the most productive way of creating speech-driven applications (compared to, say, creating a Windows-only application using Dragon NaturallySpeaking).

Application design

State-of-the-art web applications tend to adopt the Model-View-Control design pattern, where the model is a JSON finite-state machine representation of all the states (e.g. ViewingInbox, ComposingMessage) supported, and JavaScript is used as controller to create DOM/HTML views, handle user actions, and manage data transfers with the server. This is also the pattern of newer W3C specs like SCXML that aim to support “multi-modal” interactions such as requesting a mapped location on one’s mobile phone by speaking the location (i.e., speech is one mode) and having the map appear in the browser (i.e., browser items are another mode). As “pervasive computing” develops and is able to escape the confines of mobile phones and laptops, additional modes needing support are likely to be, first, recognizing that the user is pointing to something and resolving what the referent is, and secondly, tracking the gaze of the user and recognizing what it’s fixated upon, as a kind of augmented reality hover gesture. Implementing and integrating such modes is part of my interest in the larger topic of intention perception; if you are interested in how these modes fit into a larger theoretical context, I highly recommend the entry on Theory of Meaning (and Reference) in the Stanford Encyclopdia of Philosophy, and Herb Clark’s book “Using Language“.

Vxml is up to v3.0 now, and it might support integration with these non-speech modes. But vxml 2.0 and 2.1 are supported more widely, and creating applications with them that follow the design pattern above requires a bit of thinking. The remainder of this article will share my thoughts and discoveries about how to do that with an excellent freemium platform, Voxeo.com

Tips on Using Vxml 2.1

Before attempting to create a vxml application, I strongly recommend getting a book on the topic or reading the specs online. But as a quick overview, think of conversations as pairs of turns in which one person already has in mind how the other person might respond to what he is about to say, he then says it, and usually allows the other person to interrupt, and as long as the other person says something and it’s intelligible, the speaker will respond with another turn. Under this description, the speaker’s turn gets most of the attention, but the respondent’s turn usually determines what happens next. Each such pair can be conceived of as a state in a finite-state machine, where all the speaker’s reactions to the respondent correspond to transitions out of those states.
To implement such a set of states in vxml2.0 or 2.1, one can create a single text document (aka “Single Page Application (SPA)“) with this as a start,

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE vxml SYSTEM "http://www.w3.org/TR/voicexml21/vxml.dtd">
<vxml version="2.1">
</vxml>

and then for each state, insert a variant of the following between the ‘vxml’ tags:

<form id="fYourNameForTheState">
</form>

To implement each state, add a variant of the following within each ‘form’ element,

<field name="ffYourNameForTheState">
  <grammar mode="voice" xml:lang="en-US" root="gYourNameForTheState" tag-format="semantics/1.0">
    <rule id="gYourNameForTheState">
      ...All the things the speaker might expect the respondent to say that are on-task...
    </rule>
  </grammar>
  <prompt timeout="10s">...The primary thing the speaker wants to tell the respondent in this state, perhaps a question...</prompt>
  <noinput>
    <prompt>...What to say if the prompt finishes and the respondent is silent all through the timeout duration...</prompt>
  </noinput>

  <nomatch>
    <prompt>...What to say as soon as any mismatch is detected between what the respondent is saying and what the speaker was expecting in the grammar; "I didn't get that" is a good choice...</prompt>
  </nomatch>

  <filled>
    <if cond="ffYourNameForTheState.result &amp;&amp; (ffYourNameForTheState.result == 'stop')">
      <goto next="#fWaitForInstruction"/>
    <elseif cond="ffYourNameForTheState.result &amp;&amp; (ffYourNameForTheState.result == 'shutdown')" />
      <goto next="#fGetConfirmationOfShutdown"/>
    <else />
      <assign name="_oInstructionHeard" expr="ffYourNameForTheState"/> <!-- Assumes _oInstructionHeard was declared outside this form in a 'var' or 'script' -->
      <goto next="#fGetConfirmationOfInstruction"/>
    </if>
  </filled>
</field>

We’ll discuss grammars in more depth below, and the rest of the template is largely self-explanatory. But a few minor points:

  1. If you need to recognize only something basic like yes-or-no or digits in a form, then you can remove the ‘grammar’ element and instead add one of these to the ‘field’ element:
    • type="boolean"
    • type="digits"
    • type="number"
  2. Grammars can appear outside ‘field’ as a child of ‘form’, but then they are active in all fields of the form. There are cases in which doing so is good design, but it’s not the usual case.
  3. The only element that “needs” a timeout for the respondent being silent is ‘noinput’; yet, the attribute is required to be part of ‘prompt’ instead.
  4. ‘goto’s can go to other fields in the same form, or different forms, but not to a specific field of another form.

I’ve made the ‘filled’ part less generalized than the other parts to illustrate a few points:

  1. The contents of the ‘filled’ element is where you define all of the logic about what to do in response to what the respondent has said.
  2. Although I’ve indented if-elseif-else to highlight their usual semantic relation to each other, you can see that actually ‘if’ contains the other two, and that ‘elseif’ and ‘else’ don’t actually contain their then-parts (which is somewhat contrary to the spirit of XML).
  3. The field name is treated as if it contains the result of speech recognition (because it does), and it does so as a JavaScript object variable that has named properties.
  4. The field variable is lexically scoped to the containing form, so if you want to access the results of speech recognition in another form (perhaps after following a ‘goto’), then you first must have a JavaScript variable whose scope is outside either of the forms, and assign it the object held by the field variable.
  5. A boolean AND in a condition must be written as &amp;&amp; to avoid confusing the XML parser. (You might want to try wrapping the condition as CDATA if this really bugs you.)
  6. Form id’s can be used like html anchors, so a local url for referencing a form starts with url fragment identifier ‘#’ followed by the form’s id.

Note that it’s not necessary to start form id’s with “f”, or fields with “ff”, or grammars with “g”, nor is it necessary to repeat names across them like I do here. But I find that simplifying this way helps keep the application from seeming over-complicated.

Creating grammars

To implement the grammar content indicated above by placeholder text, “…All the things the speaker might expect the respondent to say that are on-task…,” one provides a list ‘one-of’ and ‘item’ elements. ‘one-of’ is used to indicate that exactly one of its child items must be recognized. ‘item’ has a ‘repeats’ attribute that takes such values as “0-1” (i.e., can occur zero or one times), “0-” (i.e., can occur zero or more times), “1-” (i.e., can occur one or more times), “7-10” (i.e., can occur 7 to 10 times), and so on. ‘item’ takes one or more children which can be any permutation of ‘item’ and ‘one-of’ elements, which can have their own children, and so on. The children of a ‘rule’ or ‘item’ element are implicitly treated as an ordered sequence, so all the child elements must be recognized for the parent to be recognized. (This formalism might remind you of Backus-Naur Form (BNF) for describing a context-free grammar (CFG). If you need a grammar more expressive than a CFG, you’ll have to impose the additional constraints in post-processing that follows speech recognition.)

If the contents of the grammar rule take up more than about five lines, it’s good practice like in other coding languages to modularize that content into an external file. Each such grammar module is declared within an inline ‘item’ like this,

<grammar mode="voice" xml:lang="en-US" root="gGetCommand" tag-format="semantics/1.0">
  <rule id="gGetCommand">
    <one-of>
      <item>
        <ruleref uri="myCommandLanguage.srgs.xml#SingleCommand" type="application/grammar-xml"/>
      </item>
      <item>
        <ruleref uri="myCommandStop.srgs.xml#Stop" type="application/grammar-xml"/>
      </item>
    </one-of>
  </rule>
</grammar>

and the external grammar file should have this form:

<?xml version= "1.0" encoding="UTF-8"?>
<!DOCTYPE grammar PUBLIC "-//W3C//DTD GRAMMAR 1.0//EN"
                         "http://www.w3.org/TR/speech-grammar/grammar.dtd">
<grammar version="1.0" xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" tag-format="semantics/1.0" root="SingleCommand" >
  <rule id="SingleCommand" scope="public">
    ...A sequence of 'one-of' and 'item' elements describing single commands you want to support...
  </rule>
  <rule id="SubgrammarOfSingleCommand" scope="public">
    ...Details about a particular command that would take too much space if placed inside the SingleCommand rule...
  </rule>
</grammar>

Defining the Recognition Result

Human languages usually allow any intended meaning to be phrased in several ways, so useful speech apps need to accommodate this by providing as many expected paraphrases as seem likely to be used. So, a grammar often has several ‘one-of’s to accommodate paraphrases. A naive approach for a speech app would be to provide such paraphrases in the grammar, and take recognition results in their default format of a single string, and then try to re-parse that string with JavaScript case-switch-logic similar to the ‘one-of’s in the markup — a duplication of work (ugh) with the attendant risk that the two will eventually fall out of sync (UGH!). What would be much preferred would be to retain the parse structure of what’s recognized and return that instead of a (flat) string; in fact, this is just what the “semantic interpretation” capability of vxml grammars offers. To make use of this capability, a few things are needed (these may be Voxeo-specific):

  1. The ‘grammar’ elements in both the vxml file and the external grammar file(s) must use attributes tag-format="semantics/1.0" plus root="yourGrammarsRootRuleId"
  2. ‘tag’ elements must be placed in the grammars (details on how below), and they must assume there is a JSON object variable named ‘out’ to which you must assign properties and property-values. If instead you assign a string to ‘out’ anywhere in your grammar, then recognition results will revert to flat-string format.
  3. If using Voxeo, ‘ruleref’ elements that refer to an external grammar must use attribute ‘type=”application/grammar-xml”‘, which doesn’t match the type suggested by the vxml2.0 spec, “application/srgs+xml”, http://www.w3.org/TR/speech-grammar/#S2.2.2

To use ‘tag’ elements for paraphrases, one can do this,

<rule id="Stop" scope="public">
  <one-of>
    <item>stop</item>
    <item>quit</item>
  </one-of>
  <tag>out.result = 'stop'</tag>
</rule>

in which the ‘result’ property was chosen by me, but could have been any legal JSON property name. The only real constraint on the choice of property name is that it make self-documenting sense to you when you refer to it elsewhere to retrieve its value.

‘tag’ elements can also be children of ‘item’s, which makes them a powerful tool for structuring the recognition result. For example, a grammar rule can be configured to create a JSON object:

<rule id="ParameterizedAction" scope="public">
  <one-of>
    <item>
      <one-of>
        <item>drill</item>
        <item>bore</item>
      </one-of>
      <ruleref uri="#DrillSpec"/>
      <tag>
        out.action = 'drill';
        out.measure = rules.latest().measure;
        out.units = rules.latest().units;
      </tag>
   </item>
   ...
</rule>

In this example, we rely on knowing that the “DrillSpec” rule returns a JSON object having “measure” and “units” properties, and we use those to create a JSON object that has those properties plus an “action” property.

‘tag’ elements can also be used to create a JSON array:

<rule id="ActionExpr" scope="public">
  <tag>
    out.steps = [];
    function addStep(satisfiedParameterizedActionGrammarRule) {
      var step = {};
      step.action = satisfiedParameterizedActionGrammarRule.action;
      step.measure = satisfiedParameterizedActionGrammarRule.measure;
      step.units = satisfiedParameterizedActionGrammarRule.units;
      out.steps.push(step);
    }
  </tag>
  <item>
    <ruleref uri="#ParameterizedAction"/>
    <!-- This use of rules.latest() should work according to http://www.w3.org/TR/semantic-interpretation/#SI5 -->
    <tag>addStep(rules.latest())</tag>
  </item>
  <item repeat="0-">
    <item>
      and
      <item repeat="0-1">then</item>
    </item>
    <ruleref uri="#ParameterizedAction"/>
    <tag>addStep(rules.latest())</tag>
  </item>
</rule>

These object- and array-construction techniques can be used in other rules that you reference as sub-grammars of these, allowing you to create a JSON object that captures the complete logical parse structure of what is recognized by the grammar.

By the way, if you want to use built-in support for recognizing yes-or-no, numbers, dates, etc as part of a custom grammar, then you’ll need to use a ‘ruleref’ like this,

<rule id="DepthSpec" scope="public">
  <item>
    <ruleref uri="#builtinNumber"/>
    <tag>out.measure = rules.builtinNumber</tag>
  </item>
</rule>
<rule id="builtinNumber">
  <item>
    <ruleref uri="builtin:grammar/number"/>
  </item>
</rule>

URI’s for other types can be inferred from the “grammar src” examples at http://help.voxeo.com/go/help/xml.vxml.grxmlgram.builtin (although these might be specific to the Voxeo vxml platform).

If you follow this grammar-writing approach, then you can access the JSON-structured parse result by reading property-value’s from the field variable containing the grammar (e.g., “ffYourNameForTheState” above), just as if it were the “out” variable of your root grammar rule that you’ve been assigning to. These values can be used in ‘filled’ elements either to guide if-then-else conditions, or be sent to a remote server as we’ll see in the next  major section, “Dynamic prompts and Web queries”.

Managing ambiguity

As a side note, if you’re an ambiguity nerd like me, you’ll probably be interested to know that Vxml 2.0 doesn’t specify how homophones or syntactic ambiguity must be handled. But Voxeo provides a way to get multiple candidate parses.

Dynamic prompts and Web queries

So far, we can simulate one side of a canned conversation via a network of expected conversational states. It’s similar to a Choose-Your-Own-Adventure book in that it allows variety in which branches are followed, but it’s “canned” because all the prompts are static. But often we need dynamic prompts, especially when answering a user question via a web query. JavaScript can be used to provide such dynamic content by placing a ‘value’ element as a child of a ‘prompt’ element, and placing the script as the value of ‘value’s ‘expr’ attribute, like this:

<assign name="firstNumberGiven" expr="100"/> <!-- Simulate getting a number spoken by the user -->
<assign name="secondNumberGiven" expr="2"/> <!-- Simulate getting a number spoken by the user -->
<prompt>The sum of <value expr="firstNumberGiven"/> and <value expr="secondNumberGiven"/> is <value expr="firstNumberGiven + secondNumberGiven" /> </prompt>

The script can access any variable or function in the lexical scope of the ‘value’ element; that is, any variable declared in a containing element (or its descendants that appear earlier). Also notice that, by default, adjacent digits from a ‘value’ element are read as a single number (e.g., “one hundred and two”) rather than as digits (e.g., “one zero two”). That’s convenient, because one can’t embed a ‘say-as’ element in the ‘expr’ result, although one can force pronunciation as digits by inserting a space between each digit (e.g., “1 0 2”) perhaps by writing a JavaScript function (see http://help.voxeo.com/go/help/xml.vxml.tutorials.java); otherwise, if the default were to pronounce as digits, then forcing pronunciation as a single number would require a much more complicated function.

I’ve said little to nothing about interaction design in speech applications, although it’s very important to get right, as anyone who’s become frustrated while using a speech- or touchtone-based interface knows well. But one principle of interaction design that I will emphasize is that user commands should usually be confirmed, especially if they will change the state of the world and might be difficult to undo. When grammars are configured to return flat-string results, prompting for confirmation is easy to configure like this:

<prompt>I think you said <value expr="recResult"/> Is that correct? </prompt>

But when a grammar is configured to return JSON-structured results, the ‘value’ element above might be read as just “object object” (the result of JavaScript’s default stringify method for JSON objects, at least in Voxeo’s vxml interpreter). I believe the best solution is to write a JavaScript function (in an external file referenced with a ‘script’ element near the top of the vxml file) that is tailored to construct a string meaningful to your users from your grammar’s JSON structure, then wrap the “recResult” variable (or whatever you name it) in a call to that function. If there is any need to nudge users toward using terms that are easier for your grammar to recognize, then this custom stringify function is an opportunity to paraphrase their commands back to them using your preferred terms.

Now we’re ready to talk about sending JSON-structured recognition results to remote servers, which is the most exciting feature of vxml 2.1 for me, because it’s half of what we need to make vxml documents able to leverage the same RESTful web APIs that dhtml documents can (the other half, being able to digest the server’s response, will be discussed soon; “dhtml” === “Dynamic HTML”, which is a combination of html and JavaScript fortunate enough to find itself in a browser that has JavaScript enabled). Like html forms, vxml provides a way for its forms to submit to a remote server. And also like html, the response must be formatted in the markup language that was used to make the submission, because the response will be used to replace the document containing the requesting form. Html developers realized that their apps could be more responsive if less content needed to travel to and from the remote server, and that if they instead requested just the gist of what they needed, and the response encoded that gist in a markup-agnostic format like XML or JSON, then JavaScript could be used in their browser-based client to manipulate the DOM of the current document and that might usually be faster than requesting an entirely new document (even if most of its resources could be externalized into JavaScript and CSS files that can be cached). Because these markup-agnostic APIs are becoming widely available, they present an opportunity for non-html client markup languages like vxml to leverage them. Vxml developers created a way to leverage these APIs by adding a ‘data’ element alternative to vxml form submission in the vxml 2.1 spec. Here’s an example:

<var name="sInstructionHeard" expr="JSON.stringify(_oInstructionHeard)"/>
<data method="post"
      srcexpr="_sDataElementDestinationUrl + '/executeInstructionList'"
      enctype="application/x-www-form-urlencoded"
      namelist="sInstructionHeard"
      fetchhint="safe"
      name="oRemoteResponse"
      ecmaxmltype="e4x" />

The ‘data’ element isn’t as user-friendly as it might be. For example, one can’t just put the JSON-structured recognition result in it and expect it to be transferred properly; instead, one must first JSON.stringify() it (this method is native to most dhtml browsers circa 2014 and to Voxeo’s vxml interpreter). And the ‘data’ element requires that even POST bodies be url-encoded, so the remote server must decode using something like this (assuming you’re using a NodeJs server):

sBody = decodeURIComponent(sBody.replace(/\+/g, ' '));
sBody = sBody.replace('sInstructionToEvaluate=',''); //Strip-off query parameter name to leave bare value
sBody = (sBody ? JSON.parse(sBody) : sBody);

What the remote server needs to do for its response is easier:

oResponse.writeHead(200, {'Content-Type': 'text/xml'});
oResponse.end('<result><summaryCode>stubbedSuccess</summaryCode><details>detailsAsString</details></result>');

If the server is reachable and generates a response like this, then the variable above that I named “oRemoteResponse” will be JSON-structured and have a ‘result’ property, which itself will have ‘summaryCode’ and ‘details’ properties whose values, in this case, are string-formatted. You have the freedom to use any valid XML element name — which is also a valid JSON property name — in place of my choice of ‘result’. The conversion from the remote server’s XML formatted response to this JSON structure is done implicitly by the vxml interpreter due to the ecmaxmltype="e4x" attribute. (The vxml 2.1 interpreter cannot process a JSON-formatted response as dhtml browsers can.) These JSON properties from the remote server can be used to control the flow of conversation among the ‘form’s in the same way we used JSON properties from “semantic” speech recognition earlier. Coolness!

A few final comments about ‘data’ elements:

  1. To validate the xml syntax of your app, you probably want to upload it to the W3C xml validator; however, the ecmaxmltype="e4x" attribute is apparently not part of the vxml 2.1 DTD, which the validator finds at the top of your file if you’re following my template above, and so you will get a validation error that you’ll have to assume is spurious and ignorable.
  2. My app uses a few ‘data’ elements to send different kinds of requests, so to keep the url of the remote server in-sync across those, I have a ‘var’ element before all my forms in which I define the _sDataElementDestinationUrl url value.
  3. fetchhint="safe" disables pre-fetching, which isn’t useful for dynamic content like the JSON responses we’re talking about
  4. If you want to enable caching, which doesn’t make sense for dynamic JSON content like we’ve been talking about but would be reasonable for static content, you’d do that via your remote server’s response headers.
  5. If the remote server isn’t reachable, the ‘data’ element will throw an ‘error.badfetch’ that can be caught with a ‘catch’ element to play a prompt or log error details, but unfortunately this error is required by the spec to be “fatal” which appears to mean the app must exit (in vxml terms, I believe it means the form-interpretation algorithm must exit). That’s a more severe reaction than in dhtml which allows DOM manipulation and further http requests to continue indefinitely. Requiring such errors to be fatal blocks such potential apps as a voice-driven html browser that reads html content, because it could not recover from the first request that fails. But maybe I’m interpreting “fatal” wrong; Voxeo’s vxml interpreter seems to allow interaction to continue indefinitely if this error is caught with a ‘catch’ element that precedes a ‘form’.
  6. If the remote server is reachable but must return a non-200 response code, the ‘data’ element will throw ‘error.badfetch.DDD’ where DDD is the response code. This error is also “fatal”.

At this point, we’ve covered all that I think is core to authoring a speech application using vxml 2.1. For more details, the vxml 2.0 spec and its 2.1 update are the authoritative references. Voxeo’s help pages are also quite useful.

Up next: Test-driven development of speech applications, and Hosting a speech app using Voxeo.

Print Friendly, PDF & Email

How to keep selected local Windows folders in sync

Some web platforms, like Apache Tomcat and Voxeo Prophecy, require their configuration files to be kept in specific locations under the platform’s installation folderpath. This creates a minor annoyance when developing for these platforms, because your IDE may not be able to add such a folderpath to its workspace. But even if the IDE can access such a folderpath, or even if you can create a symbolic link to it, the IDE might add project-related files that would confuse the web platform.

As a workaround, I’m using FreeFileSync to define rules about which items from the two folders should be overwritten by newer files from the other folder. However, FreeFileSync only syncs when prompted to via its GUI. To automatically detect new files and trigger sync, you can use the companion app RealtimeSync (which is included in the FreeFileSync installer). Yet, RealtimeSync is an app rather than a service, so you need to configure Windows to launch it whenever you start Windows or resume from sleep.

Installing FreeFileSync

  1. This app’s sourceforge page has a download button, but it will lead you through several hops before you get to a mirror at “FossHub”.
  2. The download links can be hard to find. Look in the light blue box near the top for a set of links such as “Download FreeFileSync for Windows”.
  3. During the installation, avoid Express install because it will install bloatware; use Custom Install instead.

Configuring FreeFileSync

These steps are adapted from another guide.

  1. If there are any files already in the web platform folder(s) that you want under the IDE’s control, import them to the corresponding project folder(s) in the IDE now
  2. In FreeFileSync, click the small green ‘+’ button above the left file listing pane to add as many pairs of folders to sync as you need.RealtimeSync_config1
  3. Set the left folder listing to the project folder, and the right folder listing to the web platform’s configuration folder
  4. Customize the default syncing across all folder pairs by clicking the green gear button in the upper-rightRealtimeSync_config2
  5. Cause new items in the left folder to be copied to the right folder. Cause edited items in the left folder to overwrite the corresponding file in the right folder. Note that only files introduced after RealtimeSync is first started will count as “new”, which is a good thing if you don’t want all the files in the left folder copied over.
  6. If you need to override the default sync behavior for any pair, use the small gear button that’s between the folderpaths
  7. Click OK to close, then go to Program | Save As Batch Job
  8. I recommend creating a top-level Dropbox folder called Settings where this batch-settings file can be kept.

Configuring RealtimeSync

  1. Launch RealtimeSync
  2. Go to Program | Open and select the batch-settings file you just created.
  3. Click Start.

Configuring ScheduleTasks (Windows) to launch RealtimeSync

  1. Use Windows+Q to open the start menu search box, enter “schedule”. Either “Schedule tasks” (in Windows 8) or “Task scheduler” (Windows 7 and before) should be offered. Select it.
  2. In the app that appears, select Create Basic Task.
  3. Under General | Name, enter something like “RealtimeSync after login”
  4. Set the trigger to be “On local connection to any user session”
  5. Set the action to be “Start a program” and browse to RealtimeSync’s executable (probably at C:\Program Files\FreeFileSync\RealtimeSync.exe). Under “Add arguments”, paste a complete path to the batch-settings file. (I recommend the Copy Path feature of FileMenuTools, a separate app, for this frequently-needed ability.)
  6. Under Conditions, make sure there are no dependencies on idleness, AC power, etc.

Verifying that it works

  1. Logout of your Windows session, then log back in.
  2. Edit one of the project files and save it. The FreeFileSync dialog should appear within a second or two, and disappear within a second.
  3. Verify that the corresponding file in the web platform folder has the edited content.

 

Print Friendly, PDF & Email

Testing custom REST APIs using a NodeJs http server

When you’re developing a REST API, and it’s not entirely clear how well your configuration of the client-side is working, it can be handy to get a server up quickly to log what it receives. In the Java servlet world, this might be done by introducing a filter class that inspects and logs all requests and responses. But if you don’t have the servlet itself setup yet, a faster way is to launch a NodeJs-based server locally.

If you’ve setup Eclipse IDE for debugging standalone JavaScript using NodeJs, then you can paste-in this as a new .js file and you’re almost home:

//Derived from http://stackoverflow.com/a/12007627

http = require('http');
//fs = require('fs');

port = 51100;
host = '127.0.0.1';

server = http.createServer( function(req, res) {
	
    console.log("------------------------------");

    var htmlPrefix = '<html> <body>',
    	htmlSuffix = '<form method="post" action="http://'+ host +':'+ port +'"> String value to POST (type exit to quit): <input name="formSent" type="text"/> <input type="submit" value="Submit"/> </form> </body> </html>',
    	html = null, //fs.readFileSync('index.html');
    	body = '';
    
    var generateResponse = function() {
        html = html || htmlPrefix +'Received '+ req.method + (body ? ': '+body : '') + htmlSuffix;
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(html);
        
        if (body == "formSent=exit") {
                //console.log("Exiting process");
                process.exit(code=0);
        }
    }
    
    if (req.method == 'POST') {
        req.on('data', function (data) {
            body += data;
            console.log("Partial body: " + body);
        });
        req.on('end', function () {
            console.log("Body: " + body);
            generateResponse();
        });
    } else { //GET
        generateResponse();
    }

});

server.listen(port, host);
console.log('Listening at http://' + host + ':' + port);

Once you see the console entry about “Listening…”, just open a browser tab to http://127.0.0.1:51100/.

If you can’t kill the process by entering exit into the web form, then you can kill the node process from the commandline.

Print Friendly, PDF & Email

Debugging standalone JavaScript in Eclipse IDE

There are some nice online JavaScript debuggers like jsbin.com and jsfiddle.net, but if you want to edit a .js file that’s part of a version-controlled project, you’d probably prefer to do so in an IDE.

The Eclipse IDE has the JSDT plugin that provides syntax highlighting. (And it’s baked into the “Eclipse for Java EE Developers” edition, but can be installed in other versions, too.) To evaluate the code and see the output in the IDE’s Console view, some extra steps are necessary. Z0ltan’s guide is very helpful. Some extra hints:

  1. Install nodeJs first. This is an executable that wraps Google’s V8 js engine, providing a commandline interpreter (and lots of useful libraries, I believe, such as allowing the coding of a web server using javascript). As of 2014 April 29, the Windows installer doesn’t broadcast through the OS that the Path has been updated, so as a workaround you may need to open the Environment Variables dialog and then close it with the OK button.
  2. If you copy any text from Z0ltan’s page, or this one, into your IDE, make sure to re-type all the quotes; otherwise, copy/paste tends to pick up “fancy” quote characters that cause weird errors.
  3. In between Z0ltan’s steps 1 and 2, you need to select “Program” in the left pane, and then hover over the buttons above it to select the one having hover text “New launch configuration”.
  4. There’s a comment at the end of Z0ltan’s guide advising that you add the /D flag like this:
    /C "cd /D ${container_loc} && node ${resource_name}"
    

    if your js source file might be kept somewhere other than the C drive. But Microsoft’s documentation of cmd.exe flags just says /D disables autorun, so I’m not sure how helpful that is.

The NodeJs API pages start here, and there’s some helpful guidance on error-handling on Joyent.

Print Friendly, PDF & Email

Unit-testing a Vxml app using JVoiceXml in Text mode

Installing and verifying JVoiceXml

The following steps were tested on this combination:

  • Windows 8.1 Pro 64-bit
  • JavaSE JDK 1.7.55 32-bit
  • Eclipse Juno SR2 32-bit
  1. Download the JVoiceXml 0.7.6.1GA (or higher) installer jar from http://sourceforge.net/projects/jvoicexml/
  2. Unpack that zip and double-click the jar installer
  3. Instead of installing to C:\Program Files (x86)\, install to some folder on your Desktop. (The default location runs into a permissions error for me; maybe it’s intended that the installer jar be run with Admin privilege.)
  4. When prompted which modules to install, choose “Text Implementation” (skipping jsapi through mrcp and the call manager). However, “VoiceXML Unit” through “Source Code” will probably be useful later on.
  5. Check the doc folder of your installation for the user guide, which provides further installation steps. The following steps are based on it.
  6. Open the following in a text editor: config/text-implementation.xml
    Verify that the classpath element values correspond to files that actually exist in your installation folder (even if the user guide gives different values).
  7. At a commandline, run [installation dir]\bin\JVoiceXML.exe. If you don’t see
    VoiceXML interpreter [version] started.
    

    then check the user guide for troubleshooting guidance. Leave this window undisturbed, and if you want to stop the server, make sure to use Shutdown.exe instead of closing the window or using Ctrl+C.

  8. Using Eclipse (Juno) IDE, go to File | New | “Java Project from Ant buildfile…”
  9. For “Ant buildfile” browse to JVoiceXml\demo\org.jvoicexml.demo.textdemo\build.xml
  10. “Project name” should now be auto-filled and the Finish button should be enabled.
  11. Select the project in the left pane, then select Run | Run Configurations…
  12. Select “Java Application” in the left pane, then click the button at top whose on-hover tip shows “New launch configuration”. Name the new launch config something meaningful to your memory like “JVoiceXmlTextDemo”.
  13. Select the Arguments tab, then paste
    -Djava.security.policy=${config}/jvoicexml.policy
    

    into the “Program arguments” textarea, replacing ${config} with the full path to the config folder within the text demo folder. For example,

    -Djava.security.policy=C:\Users\david\Desktop\Tools\JVoiceXml\demo\org.jvoicexml.demo.textdemo\config\jvoicexml.policy
    
  14. Select the Classpath tab. Select “User entries” then click the Advanced button. Select the “Add External Folder” radio button, then click OK. Browse to the config within the text demo folder. When you return to the Classpath tab, click Apply. If instead you select the config folder at the top-level, later you will get an error like this in the Eclipse console:
    Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
    
    javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
    
  15. Select the Main tab, then click Search to select TextDemo. Make sure the package shown for TextDemo is from jvoicexml. Click Apply.
  16. In TextDemo.java, the imports of org.jvoicexml.client.text.TextListener and org.jvoicexml.client.text.TextServer might be shown as missing. If so, select the project in the left pane, then select Project | Properties | Java Build Path | Libraries | Add External Jar, and browse to JVoiceXml\lib\org.jvoicexml.client.text.jar
  17. WARNING: I still run into java security errors like this:
    Exception in thread "JVoiceXML text server" java.security.AccessControlException: access denied ("java.net.SocketPermission" "localhost:4242" "listen,resolve")
    
Print Friendly, PDF & Email

How to monitor packets to/from Amazon Beanstalk / EC2 instances

If you need to answer such questions as

  • Is my client correctly indicating that it can handle gzip-compressed responses?
  • Is my Beanstalk-hosted webapp providing gzip-compressed responses?

then you may have no choice but to monitor packet traffic on the Beanstalk side, especially if your client is running on a mobile OS.

How can one do this? Let’s take the most difficult case and assume the only machine you have for development work runs Windows:

  1. If you didn’t associate a keypair .pem file when launching your Beanstalk environment, then create a new environment that does have such an association.
  2. On your Windows client machine, install VMWare Player 6+ and download an ISO for Ubuntu 13+
  3. Using Player, create a virtual Ubuntu desktop. You’ll also want to install VMWare Tools, which can be tricky: http://www.howtogeek.com/howto/11287/how-to-run-ubuntu-in-windows-7-with-vmware-player/
  4. In Player, go to Player | Manage | Virtual Machine Settings | Options | Shared Folders | set to “Always enabled” and add the folder containing your keypair pem file
  5. In Ubuntu’s dock, select Ubuntu Software Manager, type Wireshark into the search box, and install it
  6. In Ubuntu, open a terminal (e.g. via Ctrl + Alt + T)
  7. You should see the folder containing your pem file if you do

    ls -l /mnt/hgfs

    Sometimes even after you’ve installed VMWareTools, it still fails to access the shared folder. In this case, I’ve tried reinstalling this way:

    sudo ./Desktop/vmware-tools-distrib/vmware-install.pl

    Let’s assume it worked and the full path is /mnt/hgfs/Projects/bs-david.pem

  8. Look in your EC2 console for the Public DNS of your instance. Let’s assume it’s ec2-99-99-99-99.ap-southeast-1.compute.amazonaws.com
    1. If you aren’t sure which ec2 instance your beanstalk instance is running on, go to console.aws.amazon.com | Service = ElasticBeanstalk | Application = your app | Configuration / Edit button | Instances / gear icon | Custom AMI ID. Note down this ID.
    2. Go to Service = EC2 | Running Instances, and find the ID under the AMI ID column. Click in the Name cell of this row.
    3. The Public DNS of this instance will be listed under the Description tab (and immediately above the tabs).
  9. First, verify that ssh can connect. In the Ubuntu terminal, enter

    ssh -t -i /mnt/hgfs/Projects/bs-david.pem ec2-user@ec2-99-99-99-99.ap-southeast-1.compute.amazonaws.com

    If that doesn’t work, it might be that your network blocks the port your SSH is trying to use. I have to switch from my office’s Ethernet to its wifi.

  10. If you succeeded, the prompt should now be [ec2-user@ip-99-99-99-99 ~]
  11. At the ec2 prompt, enter

    sudo tcpdump -i eth0 -s 65535 -w test.pcap

  12. If you succeeded, the terminal should show tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes and then suspend to capture the packet traffic
  13. Using your client, send some of the requests you want to investigate. When you’re done, do Ctrl + C in the terminal
  14. Type

    ls -l test.pcap

    to ensure the file exists and is nonempty

  15. Move the pcap file from EC2 to the Ubuntu desktop by logging out of the ec2 instance and then using scp to fetch the file

    exit
    scp -i /mnt/hgfs/Projects/bs-david.pem ec2-user@ec2-99-99-99-99.ap-southeast-1.compute.amazonaws.com:test.pcap .

    Take note of the dot at the end, indicating you want to save the remote file to the current local directory.

  16. If you succeeded, you should see running updates like this: test.pcap 100% 16MB 203.8KB/s 01:18
  17. Verify that the file was transferred fully by typing

    ls -l test.pcap

    The file size should be the same as that reported by ls when you ran it on the ec2 instance.

  18. Load the pcap file into wireshark by typing

    wireshark -r test.pcap &

  19. In wireshark near the right end of the toolbar, tap the “Edit/apply display filter…” button. In the dialog that pops up, scroll down in the Display Filter list, select “http”, and click OK.
  20. Back in the main wireshark window, the second pane from the top should now show a turnkey for Hypertext Transfer Protocol.
  21. In the top pane, select the row indicating the request or response you’re interested in. Then in the second pane, open the http turnkey.
  22. For the particular scenario of checking that gzip-compression is happening, the client GETs should include “gzip” without quotes among the values of Accept-Encoding, and the server responses must have http response code 200, the Content-Type must not be text/plain, and the body shown at the right end of the third pane should not be comprehensible.

StackOverflow describes an alternative method that works even when you don’t have access to the server, if you can direct the mobile client to use your workstation as a wifi access point.

Print Friendly, PDF & Email

How to make incoming calls ring longer for Singtel mobile plans

If you have a mobile plan with Singtel, the default ring time for incoming calls is 15 seconds. You can adjust that yourself up to 30 seconds, by doing this:

  1. Go to your mobile phone’s dialer pad
  2. Enter **61*1389**30# and then press the Call button. (Change ’30’ to whatever number of seconds you want the rings to last, up to 30.)
  3. No call will be made but you should see a text confirmation.

Some bloggers indicate that one can go up to 60 seconds if one disables voicemail. (If you are a business, please don’t disable your voicemail. Providing your hours of operation in your voice greeting is very helpful.)

Print Friendly, PDF & Email

Installing Windows7 on a 12″ Motion Computing M1400 TabletPC

My job involves reading and annotating a lot of PDFs, and doing so on a tablet seems much more comfortable than using a laptop. The tablet would have to support handwriting recognition, of course, because a laptop’s keyboard would be far superior to a virtual keyboard at an odd angle right at my pelvis. As of Fall 2011, there is no native handwriting rec ability in either Apple iOS nor Google Android, and apparently none in their app stores, either. Besides, their largest displays are 10 inches (diagonally), while an 8.5×11 inch page ideally needs a 14 inch display. Also, my favorite PDF annotation tool, Tracker Software’s PDF XChange PRO, isn’t available on those platforms. Fortunately, there are tablets dating from the early 2000s that have 12 inch displays, native handwriting rec support, and designed to run the OS that my PDF tool requires (i.e. Microsoft Windows). As an added bonus, those tablets can now be bought for around US$100 even though they sold for thousands when first released.

I’ll focus here on Motion Computing’s M1400 tablet. I found one for $99 on eBay with its original digitizer pen and Windows XP installed. One or two owners before me had experimented with it, because there was no apparent way to open the Input Panel to use handwriting rec, the device buttons didnt work (except the power button), and the virtual keyboard would open only if I booted with an external keyboard attached and entered Ctrl+U during boot to activate the Utility Manager and turn on the virtual keyboard. A further problem with the hardware itself was that it got quite hot while in use, too hot to keep in one’s lap.

Installing Windows7 (the lowly Home Premium variant is sufficient) solved all of the software problems, and the device no longer gets more than mildly warm.

One new problem is that the display cannot be rotated to portrait orientation, because Intel refuses to release an updated video driver for this CPU chip for Windows7. However, some people have had success running the video driver in XP Compatibility mode, which requires installing the Professional or Ultimate variants of Windows7. I recommend installing Comodo Time Machine after the OS install and before any changes to drivers or registry settings, so you don’t have to reinstall the OS in case of an error.

By the way, I had never heard of Motion Computing before buying this device, but I am very impressed by them. They provided free tech support for a product they hadn’t sold in 5 years, it was very quick, and very thorough. If they offer a 12+ inch Windows8 tablet, especially if it has a color eInk/LCD dual display, it’ll be the first one I consider buying.

If landscape-only orientation is okay with you (and possibly no audio), here’s what you need:

  • Motion Computing M1400 tablet
  • Windows7 Home Premium installer software
  • external usb-connected keyboard with arrow keys
  • CD/DVD external usb-connected drive (or 4GB usb drive + laptop/desktop with CD/DVD drive)
  • Ethernet cable to your router

Follow these steps:

  1. The following procedure will NOT leave your files on the tablet in place. Many of them will be moved to c:windows.old, but you should probably make a backup copy of any that you would hate to lose.
  2. If you use PDF XChange 4.0 (but not the portable version), and if you have a session that you want to remember (i.e. a set of open PDFs), then be sure to note down the filepath of each (in addition to backing up the file itself in step 1 above). Although this PDF viewer is great, they don’t yet support session backup (nor syncing).
  3. If you don’t have an external CD/DVD drive, you’ll need to make the usb drive bootable. Don’t forget to copy all the installer software to it.
  4. Connect the external keyboard and the external drive.
  5. Make sure that the tablet can boot from the external drive:
    1. Reboot the tablet and the white Motion Computing screen appears, hold the digipen tip to the screen. A context menu should appear; select Launch System Setup.
    2. The PhoenixBIOS Setup Utility should open. Tap the Boot tab along the top.
    3. If you’ll be using an external CD/DVD drive, then “CD-ROM Drive” should be listed higher than “+HDD”. If it’s not, then look at the bottom and tap the white down arrow to the left of Select Item until CD-ROM Drive is highlighted in white, then tap the + to the left of Change Values to move it up the list.
    4. If you’ll be using a bootable usb external drive, then tap the white down arrow until +HDD is highlighted in white. Tap the white Enter to the left of “Select > Sub-Menu”. A submenu should open below HDD, and the external usb drive should be listed above the hard drive; if it’s not, tap the white down arrow until the usb drive is highlighted in white, then tap the + to move the usb drive higher in the submenu.
    5. When finished, tap the white F10 at bottom right to save and exit. A yes/no confirmation dialog will appear. Click yes. A beep will sound and you should exit to the Windows bootup process on your external drive.
  6. At this point, the digipen was no longer recognized for me, but the arrow keys on the external keyboard did.
  7. When you are prompted whether to enable WindowsUpdate, I recommend not doing so. It’s a great feature, but when I did this procedure the first time and turned this feature on, the installation of Windows7 SP1 introduced a bug that made several applications give errors about not having the right permissions, or not having enough space on disk, and I could not uninstall some apps like Comodo Time Machine, either.
  8. During the install process your machine will reboot, and if you booted from a usb drive, you’re going to boot from it again (unless you’re quick and yank it). If you do boot back into the install dialog again, just move the power switch to off, yank the usb drive, and power on. Installation will pickup from where it should.
  9. Once Windows7 is installed, use the Ethernet cable to connect to your router so you can get drivers, especially a wifi driver. The external usb drive and keyboard can be disconnected.
  10. To get drivers, go to Start | ControlPanel | DeviceManager, hold down the pen button while clicking on Display Adapters (i.e., do a right-click), and select “Scan for hardware changes”. This should trigger a search on Microsoft/manufacturer sites for all the drivers you need, not just display adapters. If you turned off WindowsUpdate during install, you’ll get no drivers at this point and should click the Change Setting button, then the Yes radiobutton. You should get drivers for:
    • Intel PRO Wireless 2200BG Network
    • Motion Computing Tablet PC Buttons
    • AuthenTec AES2501 (fingerprint sensor)

    Even with this, I could not get drivers for:

    • Video controller
    • Multimedia Audio Controller
    • PCI Modem
  11. You should now have wifi connection ability, so the Ethernet cable can be removed.
  12. By default, if one holds the digipen to the screen for a short while, it will be interpreted as a right-click. This is a problem if one uses a multi-level dropdown menu and wants to select anything other than the first item in one of its submenus. To disable this, go to Start | ControlPanel | Pen And Touch | Pen Options, highlight “Press and hold” in the list, and click Settings. Turn off the “Enable press and hold for right-clicking” checkbox.
Print Friendly, PDF & Email

Editing ECLiPSe constraint logic code in the Eclipse IDE

One of our projects uses the ECLiPSe constraint logic programming language (a more powerful flavor of Prolog) in conjunction with Java (which is a good way to integrate graphics, unit testing, etc). One of the most popular developer tools for Java is the Eclipse IDE (yes, same name, totally different application), and we’d like to find a similarly-powerful editor for our pure-Prolog (.pro) and ECLiPSe (.ecl) files — one that provides indicators of (im)balanced parens, coloring of built-in predicates and syntax, and maybe code completion and compiler warnings.

ECLiPSe had a project called Saros on sourceforge that aimed to provide all this functionality, plus a debugger. Unfortunately, I wasn’t able to get any of these features working in its 1.0 version (after installing it as a plugin in the IDE). I’ve also heard that development on Saros has stopped.

However, I would be happy just getting paren-balancing, and I found a way to do that in the Eclipse IDE:

  1. Go to Window | Preferences
  2. Select General | Content Types in the left pane, and then on the right, select Text in the Content Types list.
  3. In the File Associations list below that on the right side, you should see “*.txt (locked)”. Click the Add button and add “.ecl” when prompted for the Content Type. Do this again for .pl files (or .pro files, as I prefer, to distinguish from Perl files).
  4. Back in the left pane, select General | Editors | File Associations.
  5. On the right side, add “.ecl” and “.pl” (or “.pro”) if they aren’t already present.
  6. Select “*.ecl” in the upper list on the right. Then in the lower listbox, if “Standalone Structured Source Editor (default)” isn’t shown, use the Add button to select “Standalone Structured Source Editor” and then click the Default button.
  7. Select “*.pl” (or “*.pro”) in the upper list, and make sure it has the same default editor.
  8. Click OK.

Now, if you open an .ecl or .pro file using either the Java or Debug perspective, and you place the text cursor after a ) or ] that is balanced, you will see a blue rectangle around the corresponding ( or [. There is no indicator if the ) or ] is not balanced.

Note that if you quit the IDE and launch it again, you will get a warning dialog about “Unsupported content type in editor.” I believe that’s because we selected “Text” in the Content Types preferences – there being no way to add a content type for ecl and pro files in particular – and that this resulted in our files being “locked” to the generic text editor in the File Associations preference. However, by marking the structured text editor as the default, we override that locking, and you’ll notice that if you dismiss the warning, paren-balancing still works. So, I selected the checkbox for “Do not show this message again” in the warning. Relaunching the IDE again gives me paren-balancing with no warning dialog.

UPDATE: Christian Wirth said on the eclipse-clp-users mailing list: “You have to install the Web Tools Project also.”

Print Friendly, PDF & Email

How to enable TestNG launch configurations in Eclipse IDE (Windows)

When using TestNG 5.11 (and at least one earlier version, 5.9) with the Eclipse IDE 3.4.2 (Ganymede, for Windows), one can’t setup a Run configuration for TestNG in the usual way. That is, one can’t use Project | Properties | Run/Debug because only Java App and Java Applet options are presented there. (Of course, one has to install the TestNG plugin first for this to make any sense.) Instead, here’s a workaround gleaned from a post by Ajay Mehra:

  1. Make sure you haven’t hidden any launch configuration types
    1. Go to the top menu bar and select Window | Preferences.
    2. In the left pane, select Run/Debug | Launching | Launch Configurations. On the right side, make sure that Java Application and TestNG are shown and not checked. (You may have to check ‘Filter checked launch types’ temporarily in order to scroll or uncheck some items.)
  2. Make sure the class(es) you want to test have @Test annotations in them
    1. If you want to see an example, look at the SimpleTest class definition near the top of the TestNG homepage.
    2. Note that in SimpleTest, it’s not necessary to include an @BeforeClass annotation anywhere, nor is it necessary to include “(groups …)” after the @Test annotations. And rather than importing all of “org.testng.annotations.*”, you may be able to get away with just importing “org.testng.annotations.Test”.
    3. To support the @Test annotation, the IDE will want to add the testng-jdkNN.jar (where NN is 15 if you’re using JDK 1.5) to your project’s classpath.
    4. Any methods you want to be used as tests should be marked as public, so TestNG can invoke them.
      • If you don’t make any test methods public, then when you run your tests, the TestNG tab near the console tab will show that zero tests were run.
  3. Create a launch configuration for your test
    1. Go to the top menu bar and click the down-facing black triangle to the right of the Run button (a green circle with a white triangle in it). This should trigger a dropdown menu that includes “Run Configurations…” Select it.
    2. Select TestNG in the left pane, then click the New button in the upper left (the white rectangle with a yellow plus in the upper right). Enter a name for the new launch config; if your test will use just one class of test methods, that class name would probably be a good choice as a memory aid.
    3. Under the Test tab, browse to the “Project” of the test, and then select a “Run…” target. (For example, if you’re trying things out with SimpleTest, you should have created a new empty project, pasted SimpleTest.java into it, and now use the Browse button for Class to select SimpleTest.java.)
    4. If you need to provide any arguments to the JVM before the test is launched, do so under the Arguments tab.
    5. To save your edits, click Apply. When you’re done editing, click Close (or you could execute the test by clicking Run).
  4. Verify that the test is setup correctly
    1. Run the test by selecting the black triangle again near the green Run button, and then selecting the launch config you just named.
    2. The Console tab should show
      [Parser] Running:
        pathToYourProjectProjFoldertemp-testng-customsuite.xml

      The name of the xml file shown here is what TestNG generates if your launch config doesn’t use the “Suite” option and you didn’t provide your own xml file.

      Following that will be any System.out printing your test methods did, plus

      PASSED: testMethodName

      for any of your test methods that passed.

      Finally, there will be a summary report like this

      ===============================================
          SimpleTest
          Tests run: 2, Failures: 0, Skips: 0
      ===============================================
    3. A similar, more graphical view of the summary report should be available under the TestNG tab.
    4. If the report says “Tests run: 0”, double-check that your @Test annotations are on the right methods, and that those methods are public.
Print Friendly, PDF & Email

Porting Amzi prolog to ECLiPSe

While Amzi Prolog has the best debugger I’ve seen for any flavor of Prolog (and I’ve evaluated many flavors), it’s become clear that my project needs the ability to constrain variables before committing to particular values. This is the key feature difference that leads me to want to port to ECLiPSe, a flavor of Prolog where constraint propagation is the main focus. And there are other features of ECLiPSe that are very appealing:

  • Easily embedded in a Java application (via a jar that implements a JNI bridge to the native ECLiPSe executable) that allows for loose coupling through queues-and-listeners or even asynchronous queues.
  • Similar library support for manipulating terms, strings, lists, etc as other Prolog flavors
  • An Eclipse IDE plugin, Saros. (It’s not quite usable for me in its current stage but I hear a new version is imminent. And it has a Tk-based UI including debugger that’s pretty good.)

Here are the changes I had to make to my Amzi code so it would run in ECLiPSe:

  • Changed all calls using consult/1 or debug_consult to [...comma-separated filenames...]
  • Changed ‘/’ when used in predicate names to ‘_’
  • Changed import(list) to import(lists)
  • Changed all abolish calls to retractall (although this doesn’t seem absolutely necessary)
  • Changed string_term(String,Term) to term_string(Term,String)
  • Changed stringlist_concat calls to concat_string
  • Discovered that many of my variables were singletons, and changed them to start with ‘_’ (so they would be self-documenting singletons and not trigger a compiler warning)
  • Added dynamic declarations for all my dynamic predicates (Amzi probably doesn’t provide a warning when these are asserted or retracted without having been so declared)
  • Changed my (retractall(predicate(_,...)) ; true) pattern to just retractall(predicate(_,...)), since retractall never fails in ECLiPSe

I’m grateful to Dennis Merrit and Chip Eastman of Amzi for all their help in getting my initial Amzi app working, and for their excellent documentation of Prolog and Building Expert Systems.

Print Friendly, PDF & Email

Evaluating animation toolkits for ‘perception of intentionality’ simulations

Our team needs to create 2D animations that trigger the ‘perception of causality’ or the ‘perception of intentionality’ through the movement of simple shapes. (Jointed figures with faces and props can come later.) The prototypical example of such animation is the one Heider and Simmel used in their experiments in 1944, since then transcribed into Flash.

I’ve been evaluating animation toolkits with a few objectives in mind:

  1. Creating such 2D animations must be as easy as possible
  2. It must be possible to inspect such an animation programmatically to determine where each shape is in each frame. (We are creating a simulation that will “watch” the same animation, but instead of observing pixels it will read such data.)
  3. The animations must be easily distributed, such as being able to run in most browsers on most platforms using no plugin or only a commonly installed one

Here are my evaluations.

Adobe CS4 Flash Professional

PROs

  • Flash files (SWF file format) are playable on most platforms using the Flash Player browser plugin, which most people already have installed
  • There are many online tutorials about how to create animation using this toolkit, and expertise with the tool is widespread (so it would be easy to find help or hire someone)
  • The “motion tween” feature available in the CS4 version eliminates the need to copy/paste/tweak each frame into the next frame; instead, one just drags from the starting position to the ending position, and can add arbitrary curvature at many points in between by pulling on edit points.
  • Although it’s a binary file format, the SWF format has been documented by Adobe, and there is an open-source Java library, JSwiff, that provides handy wrapper accessors. It even has a forum for questions about JSwiff, but answers seem infrequent.
    • This library is a little out of date, since it refuses to process files using SWF versions after 8, but the code seems capable of handling version 10 just fine (version 10 is what CS4 Flash Pro generates). To use the library with more recent SWF versions, it seems one has to edit the source (included in the download) by changing SWFDocument.setVersion to eliminate the max version check, and then build one’s own jar file. This method refers to private member “header”, so one can’t just subclass SWFDocument and override the method.
    • The JSwiff site also offers a separate download for its inspector.bat, which provides a GUI for inspecting all tag content of a SWF. Surprisingly, it works on SWF version 10; I’m not sure how it gets around the version check.
    • Note: There is another Java library, JavaSWF, but work on it seems to have stopped around 2005 and it doesn’t handle recent updates to the SWF file format such as the DefineShape4 tag. There is a JavaSWF Yahoo group, but it seems answers are rarely provided for any questions in recent years.

CONs

  • Adobe’s tool costs US$700.
  • There is an option to Export Motion XML, which seems like a good alternative to the Java wrapper, but despite multiple attempts I couldn’t get it to include information about each frame of my test animation.

Alternative SWF toolkits

For example,

AnimeStudio Debut6

Swish MaxMini

Synfig

Toufee

PROs

  • At US$50-150, much more affordable than Adobe’s toolkit

CONs

  • Harder to use than Adobe’s toolkit because they require copy/paste/tweak of each frame of motion, and there is  no motion guide unless one sketches a path using the drawing tool and then erases that path.
  • Toufee’s min frame rate is 1 frame/sec, which is far too slow for my needs. It also has a number of bugs such as having random transition effects on by default, and making it impossible to configure an object to disappear faster than in 5 sec in the first frame
  • Although Synfig is an open-source SWF-creating toolkit, which would otherwise make it very attractive, it has such a convoluted install process for Windows that I’m not willing to put my time into evaluating it further. It seems likely that it could just break someday, and there would be too little interest in Windows users to expect them to fix it.

Alternative web-based animation platforms

For example,

HTML5’s canvas element + Javascript

Java

Microsoft Silverlight

PROs

  • Inexpensive (free) toolkits
  • Easily distributed and demo’d

CONs

  • Would require investing significant time or hiring funds into programming animations largely from scratch
  • Would require significant effort to design a way that an outside application could inspect what objects are depicted and what is happening

K-Sketch

PROs

  • Free, open-source, and allows for easy creation of motion paths
  • Allows export to SWF

CONs

  • Motion paths aren’t editable — one needs a very steady hand
  • Current release won’t run on my XP machine, and on my Vista machine the lasso selection tool doesn’t work, which means I can’t create any motion paths. Not actively supported right now, but that might change soon.

Bottom line: Assuming one can afford Adobe’s Flash toolkit, the combination of it and the Java wrapper seem like a very workable solution.

Tip: If you need to control the playback of an SWF using Java, it seems the best option is a hack where a native SWF player like XULRunner is controlled by Java by injecting Javascript. Have a look at the DJ Native Swing project. It’s hosted on Sourceforge and has discussion forums there.

Print Friendly, PDF & Email

A font for eco-friendly printing

So you already print double-sided or reuse single-sided prints? You can go even further in your quest for eco-friendly printing.

A font has been developed that reduces the amount of toner used while minimizing loss of readability. The download page includes tips on how to install on a variety of platforms, and here’s a tip for installing a font in Windows 7. Note that after clicking the “Install” button for a font, there is no indication of success beyond the Install button becoming disabled — although you can open the Fonts control panel to verify success.

Print Friendly, PDF & Email

Open a page in the default browser following a schedule

The notification component of our wiki (plone) isn’t useful enough to bother with, so as a workaround I view its “Recent Changes” page on a regular basis. Well, as regularly as I can remember, which hasn’t been regular enough. So now I use Windows7’s Task Scheduler to open the page for me on a repeating schedule.

This should also be useful for catching regular Internet radio programs.

Steps:

  1. Start | All Programs | Admin Tools | Task Scheduler | Create Task (in far right pane)
  2. General tab
    • Enter a name you’ll recognize later
  3. Triggers tab | New…
    • Enter when the task should occur
  4. Actions tab | New…
    • Action = Start a Program
    • Program/script = rundll32
    • Arguments = url.dll,FileProtocolHandler http://yourFavoriteSiteHere.net
  5. Conditions tab
    • Start only if the computer is on AC power => off
    • Wake the computer to run this task => on
  6. Settings tab
    • Run as soon as possible after scheduled start is missed => on
Print Friendly, PDF & Email

Portable Windows with/without admin privilege

Update: SORRY! It turns out that VirtualBox ties its configuration very closely to specifics of its host machine (such as through the MAC address), so I have to back away from the “portable” claim in this post’s title. Until VirtualBox realizes the value to them of supporting portability, using VirtualBox won’t actually help you go portable.

Previously, I described how to get some freedom from the “no admin privilege” restriction that many workplace computers have. That technique involved running specially-built versions of one’s applications from a thumbdrive. After trying that for a month or more, I grew tired of the following limitations:

  • Many useful apps aren’t built to run from a thumbdrive, often because they use the registry
  • Going back to Firefox from Chrome wasn’t a good fit for me (and Chrome isn’t really portable yet)
  • One can’t control default applications; for example, one can’t directly open links in messages in portable Thunderbird using one’s portable browser

There is a framework called qemu that allows running an entire operating system from a thumbdrive, and it can do so in a mode that doesn’t require admin privilege. But this mode can’t access USB peripherals like keyboards, mice, and other drives connected to the host computer. The final deciding factor against qemu for me is that OSs make many writes to the storage they boot from, and thumbdrives allow only thousands of writes before their storage capability degrades.

If you really want to try qemu before my final solution, here’s what I tried with it:

  1. Install Qemu manager on usb
  2. Set VM RAM to 512MB
  3. Give the VM whatever name you want, and whatever OS label you want…I used “Windows7Portable” for both
  4. Start VM
  5. In VM/Qemu Client, click CD Drive button in menu bar and browse to your Windows 7 RC ISO file
  6. Wait while OS installer gets going…I had to quit and go to bed before it finished

Here are some related links that were helpful:

Because qemu would not be able to use usb-connected keyboard and mouse, because I’d have to copy it to a new thumbdrive fairly often, and because it would be pretty slow by most accounts, I decided to give up on the “no admin privilege required” goal. Instead, I asked my IT dept to install VirtualBox. The following steps were inspired by a Lifehacker post.

  1. Get a portable hard drive. I got a Maxtor 160GB “Basics” model for about US$60.
  2. Plug in the drive to any machine you plan to use where you don’t have full control, then check that you can write to it. (For example, right-click in the drive contents shown in Windows Explorer and choose New | Text Document.) If you can’t write to it, ask your IT dept to grant you write permission for it.
  3. If you’re going to overwrite a virtual disk file you may already have on the portable drive, and you use Chrome, be sure to export your bookmarks and open tabs to the host first. (ouch)
  4. Have VirtualBox installed. Then copy its .VirtualBox directory to your portable hard drive.
  5. Start VirtualBox and go to File | Preferences | General. Change “Default Hard Disk Folder” and “Default Machine Folder” to .VirtualBoxHardDisks and .VirtualBoxMachines on your portable drive.
  6. In VirtualBox, press the New button.
  7. Click through the Next buttons, including leaving virtual memory at 512M.
  8. Click through more Next buttons, including the creation of a new boot (virtual) hard drive of size 20GB. This virtual drive will be kept in .VirtualBoxHardDisks
  9. Choose Dynamically-Sized storage
  10. Take a lunch break while the VDI is created. I also created a brief “reward if returned” text file with contact info at the root of the portable drive.
  11. Once your virtual drive is created, click the Settings button, then the CD/DVD tab and the Add button, and browse to the ISO file of the OS you want to run in the virtual machine. For me, this was Windows 7 RC and my “host” is Windows XP. Click Ok and return to the main VirtualBox window.
  12. Click the Start button. You should eventually see the OS installation prompts. Answer the prompts the way you would if you were installing to a machine sitting right next to your current one and on the same network.
  13. When the OS has been installed (it may need to reboot itself within the window a couple times, but won’t affect the rest of your computer), go to Devices and select Install Guest Additions. This will make it much easier to use your keyboard and mouse. (If you have difficulty getting to the menu, hit the Ctrl key on the right of your keyboard and then try again.)
  14. Once the OS is installed, you can move or delete the ISO file. If VirtualBox complains about not being able to find the ISO file, just use the button to remove it from the CD/DVD mounts.
  15. To get access to folders on the host machine:
    1. Turn on sharing for each of the folders you want to access.
    2. In your VM window, go to Devices | Shared Folders. The “Folder Path” browse button should allow you to select one of the folders you just shared
    3. To make the shared folder appear among the drives shown under Computer in your VM OS (“the guest machine”), go to the Start menu, type in “cmd”, and then type in “net use s: \vboxsrvMyHostFolder” where MyHostFolder is replaced by the name of a folder you shared, and where s: is replaced by a drive letter not already in use.
  16. You should now be able to copy all the data folders from your host to the guest.
  17. Go ahead and install all the apps you need on the guest. I have some recommendations:
    1. Do not install an antivirus program. They can make your guest unusable by turning its display to snow and ignoring your commands. This is the most significant sacrifice I’ve encountered so far.
    2. Use Mozy to backup your data. The first 2GB is free, and you won’t have to remember to backup again.
    3. Windows Explorer settings
      • Change default folder to Computer
        1. Right-click on Windows Explorer in taskbar
        2. When “Windows Explorer” appears in the “jump list”, right-click on it and select Properties
        3. For Target, enter
          %windir%explorer.exe ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}
      • Organize | Folder and Search Options | View
        • Show hidden files, folders, and drives => checked
        • Hide extensions for known file types => NOT checked
        • click Apply to Folders and have it apply to all folders
    4. Control Panel | Programs | Turn Windows features on or off | Games => NOT checked
    5. Control Panel | Taskbar and Start Menu | Start Menu | Customize
      • Computer, Control Panel, Personal folder = > Display as menu
      • Documents, Games, Music, Pictures => Don’t display
      • Run => checked
      • System admin tools => Display in All Programs and the Start menu
      • Use large icons => NOT checked
    6. Pin to taskbar: Cmd shell, Calculator, CharMap
    7. Set built-in Windows Defender (anti malware) to run everyday over lunchtime instead of at 2am, since the portable drive may be disconnected overnight.
    8. Media players like Winamp stutter when run in a VM. I run them from the host instead.
  18. If some of the options for setting screen resolution in your guest are disabled, you might be able to enable them by running this in a cmd window in the host:
    C:Program FilesSunxVM VirtualBox>VBoxManage setextradata global GUI/MaxGuestResolution any
  19. Whenever you need to take the portable drive with you, go to Machine | Close | Save Machine State. All your open windows and state will be saved and the VM will close. Quit VirtualBox so it doesn’t hold onto the VDI file on the drive, then unmount the drive via Safely Remove Hardware. If something still won’t let you unmount, then you may have to shutdown the host.
  20. I have been closing down my VM every night, because when I’ve allowed it to run for several days before shutting down, VirtualBox seems to get stuck in a “stopping” state. It’s not clear if this is a bug in VirtualBox or a behavior in Windows 7 that can be configured not to happen.
  21. Finally, as a note to myself, here are some preferred Win7 settings and applications:
    1. Desktop context menu | View | Small icons
    2. Unpin Windows Media and IE from taskbar
    3. Taskbar properties:
      1. Use small icons
      2. Dock at bottom
      3. Never combine/stack buttons
    4. My favorite apps:
      • Java 1.6 SDK with Netbeans
      • Chrome from the dev channel
        • Create a shortcut and append –enable-sync to the Target value
        • While I would like to pin the shortcut to the taskbar, I’m not sure the –enable-sync flag would survive that, so I put the shortcut in the Startup folder instead. (My bookmarks on different machines have been out of sync for a few days, and I suspect this is because I was starting the browser from the taskbar.)
        • Install AdSweep ad-blocker extension by clicking here
        • under (wrench menu)
          • Turn on syncing of bookmarks
          • Always show bookmarks bar
          • under Options
            • under Basics
              • On startup | Restore the pages that were open last
              • Home page | Show Home button on the toolbar => off
            • under Personal Stuff
              • Passwords | Offer to save
              • Themes | Get Themes | Themes by Google | Greyscale
            • under Under the Hood
              • Download location | Desktop
              • Ask where to save each file before downloading => off
        • Right-click on these tabs and select Pin to tab:
          • Evernote
          • Gmail
          • Gmail calendar
          • Google reader
        • Right-click in address box and select Edit Search Engines, then change these keywords:
          • Wikipedia => w
          • Google Scholar => s
          • Lifehacker => l (small L)
          • Amazon => a
          • Google groups => g
          • Download.com => d
          • Google image search => i
          • Youtube => y
          • Ebay => e
        • Wishlist: Save session/open-tabs, Pinned tabs, and Search Engine Settings to Google bookmarks or some obvious file that I could backup
        • Wishlist: An official theme that matches my Windows default theme!
      • Mozy
        • I keep all my files in 4 desktop folders; I backup only parts of these:
          • Business
          • Papers: Articles by others in PDF and HTML format
          • Projects: Workspaces for IDEs, Todo lists, etc
          • Tools: Portable apps, Printer drivers, Installers
        • Schedule | Alert me if a backup hasn’t happened in this many days => 1
        • Options
          • Notify me when a backup starts => off
          • Show status when a backup successfully completes => off
      • portable Thunderbird email client with Lightning calendar extension
        • Pin to taskbar
      • Notepad++
        • Pin to taskbar
        • Settings | Preferences
          • Global
            • Toolbar | Hide => checked
            • Tab bar | Vertical => checked
            • Tab bar | Enable close button on each tab => checked
          • Misc | Remember current session for next launch => checked
      • portable PDF XChange Viewer
        • Pin to taskbar
      • IZArc unzipper
        • During install, make these settings:
          • Explorer Enhancements tab: Extract Here, Extract to <folder>, Email, Create self-extracting, Test, Display icons on context menus => NOT checked
          • Program Locations tab: Default viewer => Notepad++
        • Wishlist: a setting that allows “Extract all subfolders” as the default
      • OpenOffice
        • Pin to taskbar
      • doPDF virtual printer (use browser’s Print command to create PDF version of webpages for archiving)
    5. Pidgin
      • Don’t pin to taskbar; it will be added to hidden system tray
      • Buddies | Show | Offline buddies
      • Create shortcut and drop in Startup folder
      • Preferences
        • Interface | Show IMs and chats in tabs => off
        • Conversations | Enable buddy icon animation => off
        • Sounds : Enabled only for “Message received”
        • Logging | Log all instant messages => on
    6. TweakLogin
    7. Google Calendar gadget. Move to lower right corner.
    8. Amzi Eclipse IDE version 8 for Prolog and Java
      • Pin to taskbar
      • Set workspace to DesktopToolsEclipseWorkspace
  22. One would think that “.pdf” would appear at Control Panel | “Associate a file type or protocol with a program” but it doesn’t. Instead, double-click any PDF, choose “select a program”, choose your PDF viewer, and make sure the checkbox is checked for “always use the selected program”. (This entire step is probably only necessary because I use the portable version of the viewer, and it doesn’t create entries in the registry.)
  23. Go to Control Panel | Devices&Printers and add the office Grayscale and Color printers
  24. Get more free wallpapers from Microsoft
Print Friendly, PDF & Email

How to sync Windows Mobile with both Exchange and Google

For Windows Mobile phones, Google suggests that you use the ActiveSync program on the phone to connect to one of their servers. This is problematic in principle for me, since ActiveSync allows only one connection with a server to be configured, and I need that to stay synced with work email. It also didn’t work even when I experimented, first with ActiveSync, and later with Funambol’s WinMo client.

What did work was the free GMobileSync client. The 1.3.7 beta version supports multiple Google calendars, but one cannot select to sync just a subset of them, nor are secondary calendar events shown any differently than events from one’s default calendar. (Suggestion to GMobileSync: Allow defining a 2-letter uppercase code per calendar in device settings; strip these when syncing back to the server so they don’t appear to have changed.) It doesn’t sync contacts, but that feature is said to be coming. And syncs can’t yet be scheduled to happen automatically (but you can get CT Scheduler Lite free and tell it to launch the sync, but then you still have to press the Sync button — there is no parameter to automate that part yet; to install, download to a machine where you have admin privileges, or email them for the CAB file).

As part of your move away from Microsoft, at least on the desktop, you may want to use Mozilla Thunderbird+Lightning to manage your Google Calendar.

You may also want to try FinchSync with GCalDaemon.

If you want to try it the way Google suggests, you might need help from this and this (from these matches) and use Funambol client for WM with these settings:

Server URL: https://m.google.com:443/syncml

User: [yourname]@gmail.com

Password:[your gmail password]

If you really want to use ActiveSync with two servers, it’s said to be possible, but one must first find a way to edit the device’s registry:

So, to sync two exchange servers, put this in the device’s registry:

[HKEY_CURRENT_USERSoftwareMicrosoftActiveSyncEnableNonLocalCrossPollination]
= (DWORD) 1

This key will most probably be there already, but if it is, its value
will be 0. If so, change it to 1.

Soft reset, then, setup activesync ON THE DEVICE (If you try setting up
on the PC, it will still fail).

There are also paid services that are geared to people who want more features or who want to avoid doing all this IT work themselves:

  • http://www.scheduleworld.com/
  • http://www.goosync.com/
Print Friendly, PDF & Email

Comparison of tools for rule-based inference

Although I started writing pseudo-code rules a few weeks ago, I’ve suspended that while I look for a tool for writing and testing rules so I don’t assume too much about the quality of the rules so far. This post describes what I’m looking for and the tools I’ve looked at. I’m likely to go with JIProlog or Amzi Prolog (and perhaps later, ECLiPSe).

I’m looking for an expert system-type tool that offers these features:

  1. Simple, first-order-predicate-calculus (FOPC) syntax rather than C-style code
  2. Can be embedded easily in Java programs
    • Prefer Java because it’s platform-independent
    • Java has widespread use in simulation research that I might use or partner with
  3. Has a large, active community that might be interested in my work, and from whom I might get tech help
  4. Has good IDE (editor tool) support for auto-completion, syntax-highlighting, breakpointing, etc
  5. Allows for easy changing of any rules governing beliefs, desires, and intentions (aka BDI)
  6. Has a way of tracking what papers/scenarios influenced the conditions and actions of each rule (aka “provenance tracking” in my terms)

This is what I’ve found:

Jason

PROs

  • Uses a Prolog-like syntax (i.e. fairly similar to FOPC)
  • Has a jEdit-based IDE that allows inspecting the mind of each agent, and history of actions among the agents
  • There is a book with in-depth how-to info (which I’ve ordered)

CONs

  • Structured as a “BDI” system, which sounds at first like a big positive, but on deeper inspection seems to mean that it handles beliefs, desires, and intentions in a pre-defined way. I’m not sure yet how limiting this might be.
  • I asked the creators if there was a compelling reason to use it over a simple inference engine (apart from the ability of MAS frameworks to allow agents to run over a network), and they said there isn’t much advantage in that respect.
  • Might not support back-chaining or facts with universally-quantified vars (however, this might be possible in Jason and all Rete-based systems by encoding such facts as rules with “true” as their antecedent)

JADEX

PROs

  • Java based
  • Has its own BDI debugger tool

CONs

  • BDI support seems “cooked in” and likely to be hard to change
  • Rules must be expressed in an especially verbose form of xml
  • Might not support back-chaining or facts with universally-quantified vars

JAM

PROs

  • Java-based BDI
  • Distinguishes between achievement goals and maintenance goals
  • Seems more comprehensive in BDI concepts than similar systems

CONs

  • Procedural rather than FOPC-style syntax
  • Seems to have same limits on expressiveness (i.e. fairly restricted compared to FOPC or Prolog) as other forward-chaining expert system tools using the Rete clause-indexing algorithm

Discrete Event Calculus Reasoner (DECL)

PROs

  • The “event calculus” (EC) is a set of rules for dealing with the frame problem (aka “commonsense law of inertia” — things tend to stay as they are unless explicitly changed). The frame problem occurs when a rule system knows a fact was true in the past but isn’t sure whether to assume it’s still true. CCSS is likely to run into the frame problem often, since our systems are likely to be triggered by combinations of mental attitudes, but some of those attitudes may seem “stale” due to being triggered in the past. The “discrete” part in the name is due to assuming a timeline with discrete points rather than a continuous one.
  • Has a book that shows how to encode BDI and OCC in EC

CONs

  • Requires integrating Unix env, Python, “PLY”, and one of a small set of SAt logic solvers. This seems too brittle and platform-specific to me.
  • While EC has a good-sized community, this inference engine seems to have a small one
  • Seemingly no IDE support
  • Might not support  facts with universally-quantified vars

Clips

PROs

  • FOPC-like syntax

CONs

  • C-based, so integrations would have to use C, JINI, or system-level calls

Jess

[also see Jess vs Prolog]

PROs

  • Clips syntax implemented in Java
  • Has an Eclipse (IDE) plugin
  • Widely used

CONs

  • Roundabout support for facts with universally-quantified vars: One must use the special ‘nil’ slot value for such vars. Not sure if this will actually work.
  • Roundabout support for backchaining: Instead of indicating that a particular rule is backchaining, one must commit to making a particular predicate backchainable. This seems like it could have unwanted side-effects.

ACT-R

Uses special jargon — “chunk” is what most other systems call a fact; “declarative memory” (for chunks/facts) is what other systems call “working memory”; “procedural memory” is where production rules are kept (is this an oxymoron only to me?)

Structured very similarly to BDI toolkits — there is a goal buffer and a retrieval/belief buffer, but unlike BDI these buffers are allowed to hold only one fact/chunk at a time.

PROs

  • Very popular among “cognitive modeling” community

CONs

  • Limiting the size and number of buffers seems unnecessarily limiting — it limits the expressiveness of rule conditions
  • Seems to be no support for universally-quantified vars in facts, especially because vars are not allowed to bind with ‘nil’ in facts
  • Coded in Lisp, and special purpose IDE is very limited but does have a stepper (but perhaps not breakpointing)

Soar

Similar jargon as ACT-R.

PROs

  • Fair-sized community in AI and Psychology (e.g. John Laird of UMichigan)
  • Formalization of Cohen & Levesque’s teamwork theory exists, STEAM, created at USC by Milind Tambe’s group. (I strongly suspect any team- or cooperation-related work we do will have to build on C&L’s theory.)
  • Java-based
  • Has its own IDE

CONs

  • Would prefer Eclipse plugin to specialized IDE
  • Syntax allows for separate stages of “proposing” and “adopting” operators, and a lot of flexibility in conflict resolution. I don’t currently need this, though, and the syntax is somewhat different from traditional FOPC. I think I could migrate to Soar later if needed.
  • Not sure if Soar has negative connotations for roboticists and AI folk, due to its somewhat dogmatic views on cognitive architecture

LEADSTO

Prolog-based simulation tool. It’s been used by its creators for simulating many domains, including a prey animal that anticipates a predator’s actions (by simulating the predator’s mind) and counteracts.

It appears to have some sort of unit-testing support built-in. Perhaps embeddable in a Prolog/Java bridge.

JBoss Rules/Drools

[IBM tutorial]

PROs

  • Very active community (enterprise)
  • Not only an Eclipse plugin but also a browser-based “rule management system” (not sure of its features yet)
  • Java-based

CONs

  • Two primary rule languages – one in “natural” but highly constrained English, and one that mixes FOPC with procedural constructs. There is a nascent effort to provide CLIPS/Jess-style language support also.
  • Doesn’t support backchaining
  • Probably doesn’t support facts with universally-quantified vars (unless through a workaround like Jess’)

Prolog in Java [external overview]

PRO: Prolog supports backchaining and facts with universally-quantified vars

  • JIProlog
    • PRO: Java can call Prolog, and vice versa
    • PRO: Available as shareware (free)
    • PRO/CON: Special-purpose IDE
    • PRO: Actively supported
  • AmziProlog
    • PRO: Java can call Prolog, and vice versa
    • PRO: Has a plugin for Eclipse IDE
    • PRO: There is a breakpointing debugger available for the IDE plugin
    • PRO: Good support through Amzi forums
    • CON: The breakpointer is not free
    • CON: The breakpointer, and the interpreter, require some getting used to. For example, the listener must be shutdown manually (via a “quit” typed command) before one exits Eclipse. Common keyboard shortcuts cause errors when the Listener has focus.
  • ECLiPSe
    • An extension of Prolog that supports “constraint programming”. In my terms, this allows one to make temporary bindings such as “T > 2” rather than only permanent absolute bindings like “T = 3” as pure Prolog demands, thereby delaying commitment to a specific value. This is a way to be efficient by doing search in a “constrain and generate” style rather than a “generate and test” style. For example, if one wanted to know if “the book was returned before Monday”, one could constrain a time variable to be before Monday and then search for book return events using that time variable, instead of searching for all book return events using an unbound time variable and then checking each variable binding to see if it was after Monday.
    • However, one is limited to relations for which a “constraint solver” can be written; ECLiPSe comes with several solvers for different kinds of problems.
    • A plugin for the Eclipse IDE is available, Saros, but I couldn’t get version 1.0 working. It was contributed by a Cisco employee, and rumor is that he will get official support to update it. I’ll re-evaluate when that happens.
  • JPL
    • PRO: Java can call Prolog, and vice versa. Commonly used with free SWI-Prolog
    • CON: Not actively supported since 2003 (at least not the docs)
  • tuProlog
    • PRO: open source, and appears actively supported
  • JLogic
    • PRO: Free
    • PRO/CON: Special-purpose IDE
  • Jinni
    • CON: Not free
  • SICStus Jasper
    • CON: Not free
  • GNU Prolog for Java 0.1.0
    • PRO: Free
    • CON: Very early release
    • CON: Appears not to be actively supported
    • CON: No IDE

Cyc engine and tools (but not KB) – TBD

Currently can’t run on Vista; will try on XP or Linux soon

RePast – TBD

Swarm – TBD

Cogent

Targeted at situation-assessment and decision-making applications. Uses Bayesian network as part of its tech.

PROs

CONs

  • Appears to be not available, except perhaps through a belief net app from Charles River Analytics
  • “On the situation assessment side, one major problem we are confronted with is that the type of belief network currently used in COGENT does not model temporal information explicitly.”

MatLab

PROs

  • Popular in research community

CONs

  • Seems limited to numeric-oriented simulation rather than rule-based ones
Print Friendly, PDF & Email

Prevent HTC phone from switching to Ulaanbaatar time from Singapore/Malaysia time

My HTC Hermes (AT&T 8525) keeps switching from the time and zone I set in Settings — in particular, from Singapore/Malaysia’s timezone to Ulaanbaatar’s. I found just one Google match about this problem: http://www.ppcsg.com/lofiversion/index.php/t93410.html, and it indicates the problem also affects the HTC Touch. The solution is to go into the Phone app, Menu, Options, find the Time Zones tab on the far lower right, and uncheck “Automatic change time zone and clock”.

Print Friendly, PDF & Email

Implementing Calendar Sync via Funambol

Sync software for managing contacts, events, etc across devices can be very helpful when it works, and very frustrating when it doesn’t. In my experience, when an error occurs it’s often unclear how to rectify it; and even when there is no error, it’s hard to judge whether it worked because many updates may have been made to my data and it’s unclear whether the updates were correct until I run into an instance of not being able to find a contact, or finding that I have multiple instances of the same reminder.

I was really motivated to find a solution, and recently I had the opportunity because my employer chose to offer a sync service by using the open-source software shepherded by Funambol.com. This article describes how to use Funambol’s software to allow users to sync with a pre-existing store of their event and task data.

Funambol provides a very capable sync platform that gets one past the fundamental technical challenges and will allow you to focus on the usability issues that all current sync experiences have.

What Funambol Provides

The core piece of Funambol’s software suite is the Data Synchronization Server (DSS), comprised of Tomcat 5.x running a webapp that handles the syncML xml-over-http protocol plus a dbms (mysql, postgres, or hypersonic) for state persistence. There is also a webapp (“webdemo”) providing an html interface for managing events and contacts, to be stored in the same dbms, but this article is about using pre-existing storage, so you won’t want to use this webapp or its db tables.

Another major part of the suite is the large stable of plugins for mobile devices. Most smartphones and PDAs (even the iPod) have calendar and contact functionality, where the data is stored in a local file or dbms. Many of these devices also have factory-installed (“native”) sync software, which works by sending a “begin sync” request encoded in syncML wirelessly(*) to a server that knows how to coordinate sync attempts. (*Strictly speaking, a device doesn’t have to have a wireless connection; instead, like the iPod, it might require a cable to a desktop computer, which itself has to be connected to a network unless you’re syncing only with the desktop itself.) For devices which do have contacts or events storage but no native sync client, one can usually find a “plugin” from Funambol. Unfortunately, finding out whether your device already has a sync client can be difficult, since the app might be hiding several folders deep from your main menu.

If you don’t have a sync client, but do have the ability to install software directly on your device, you can look for the plugin at https://www.forge.funambol.org/download/. If you don’t have the ability to install directly, but your device can receive binary SMS messages, then you can signup for a free user-oriented account at http://my.funambol.com, where you can indicate your device type and trigger an SMS containing the plugin software — all you have to do is click on an install link in the message.

There are some surprises in the devices that Funambol does support and those it doesn’t. It does support Microsoft Outlook (via a plugin), allowing data there to be synced with your pre-existing storage even without an Exchange server being involved. But it doesn’t support OS X’s Sync application. It does support the iPhone for syncing contacts only, but not events (because, I’m told, the iPhone SDK doesn’t support access to the device’s calendar storage). It does support the iPod, but only if you can connect it to a Windows desktop (via the iPod’s USB cable, which talks to a plugin from Funambol that you must install); there is no support for using an iPod via a Mac (and since the iPod has no wireless capability, it’s dependent on being tethered to some desktop). Another wrinkle is that some carriers disable the native sync clients on phones they sell, or they block Funambol’s plugins from using the wireless connection unless Funambol has been certified. With new phones arriving all the time, this makes for a moving target.

Two more major pieces of Funambol’s suite are the “sync portal” and the “PIM listener”. These are not available in the free, open Funambol software but can be gotten in the “carrier edition” through agreement with Funambol. The portal is another webapp using the same dbms, providing an http-based API, which can be used to build a website allowing users to indicate their device type and trigger an SMS containing an installable plugin (similar to what my.funambol.com provides).

The PIM listener is useful for users who have several devices that must stay in synch; it notices when one of a user’s devices has been synced, and triggers an SMS to all the user’s other devices (which are known to support such SMSs) instructing them to automatically initiate their own sync to pick up the changes. Obviously, this won’t help with Outlook or an iPod (because they can’t receive SMS notifications), but is a good way to satisfy one’s most-engaged users, who tend to have lots of other toys. I believe that if one updates device A, makes a separate update to device B, and syncs A, then not only will B be auto-synced, but the result of that sync will trigger an auto-sync of A to pickup the new data from B. However, as the number of a user’s devices goes up, the number of auto-syncs may thus increase factorially/exponentially; I know of no tests to see if this leads to significant battery drain or application latency. For a demo, check out the video interview with Funambol’s CEO at TalkTv.

As a last note, although the sync portal allows plugins to be pre-configured to connect with one’s own DSS, I don’t know if it’s easy to configure such plugins for locales other than US English. Also, I believe there is no publicly-available list of all error messages that a user might encounter, for use in one’s own Help page.

How Sync with DSS Works

Once a user has located the native sync client on their device, or installed a Funambol plugin (actually, any syncML client from any software provider should work, since Funambol’s DSS is syncML-compliant), and has gotten a login from the data provider (e.g. mail.aol.com or my.funambol.com) to enter into the client, they are ready to start. Actually, there’s one more step: Make sure the data provider url is correct in the sync client.

When the “synchronize” button is pressed, a “begin sync” syncML message is sent to the data provider’s url along with the user’s login, a deviceId (unique to the device compared to all other devices in the world), and an indicator of what kind of data to sync (i.e., contacts, events, or tasks). The data type is actually mapped to a “sourceUri” in the device — for example, some devices allow syncing events using either sourceUri “scal” (indicating the SIF Event format) or sourceUri “event” (indicating the VCalendar format). The sourceUri values are arbitrary and depend on how the DSS has been configured, but the values given here are Funambol’s plugin defaults. I recommend using SIF formats if possible, since they appear to allow for a wider variety of event data, and are common on Microsoft devices and thus have a large user base and the implicit testing that comes with that.

If the login is approved, the DSS combines the userId and deviceId into a “principal id” and checks its fnbl_last_sync table to see if this principalId+sourceUri has synced with it before; if not, it’s treated as a “slow” (aka full, complete) sync; if it has synced before, it’s treated as a “fast” (aka incremental, partial) sync. For slow syncs, DSS responds in syncML by asking the device to send an id for each data item of the requested type; for fast syncs, DSS asks the device to send only id’s for the data added, updated, or deleted since the last sync (as indicated by the date in fnbl_last_sync). DSS makes a similar slow-or-fast request to the data provider end.

Who or what is this data provider? If you use the DSS’s “webdemo” webapp for managing contacts and events, it’s a set of tables in DSS’s dbms. But in our case, it’s a “calendar server” that serves many other client applications and which we access via the network. More on this later.

For a slow sync, DSS asks the device for the full data behind each data item id, and passes that to the data provider telling it to add it. The data provider must reply with an id for the new item. Similarly, DSS asks the data provider for the full data behind every id, and passes that to the device telling it to add it. The device must also reply with an id for the new item. DSS stores the pairs of {device event id, data provider event id} in db table fnbl_client_mapping, keyed by principalId and sourceUri. (Note: if you reinstall a plugin, the deviceId is likely to change, so the principalId would change, which means that syncing, then reinstalling and syncing again, is likely to lead to duplicates on both the device and data provider ends, because there is no longer a matching principalId in fnbl_last_sync and thus a slow sync is done the second time.)

For a fast sync, DSS asks the device and data provider ends what has been added since the time of the last sync, sends the new items to the other end, and updates the mapping table with the new id’s. It then makes a similar request to both ends for items updated since the last sync, and then for items deleted since the last time.

On the data provider end, DSS makes all its requests through “modules” which must implement a predefined API. But before a sync can occur, the userId and password that a user entered in the device must be authenticated, and each module is responsible for indicating what Java class should do the auth check. Funambol calls such an auth class an “Officer”, and provides a default one that checks the co-installed dbms for a matching login. Since we are focused on using pre-existing data providers, you will want to write your own Officer to connect with your existing auth service for user accounts.

The module API requires implementation of these signatures:

  • beginSync – Called by DSS if the officer indicated successful auth; the principalId and sourceUri are passed in via a context parameter
  • getAllSyncItemKeys – DSS uses this to get data item id’s when starting a slow sync
  • getNewSyncItemKeys – DSS uses this to get data item id’s for fast syncs, to get items added since last time
  • getUpdatedSyncItemKeys – DSS uses this to get data item id’s for fast syncs, to get items updated since last time
  • getDeletedSyncItemKeys – DSS uses this to get data item id’s for fast syncs, to get items deleted since last time
  • getSyncItemById – If DSS wants the device to add or update something, it gets it from the data provider this way
  • getSyncItemKeysFromTwin – The user might have added similar items on both the device and data provider ends; this call gives the data provider a chance to report items it thinks are similar to the given device item, to avoid adding duplicates at both ends.
  • addSyncItem – If the device has an item the data provider should have, DSS uses this to put it there
  • updateSyncItem – If the device has an item that should replace one the data provider has, DSS uses this to put it there
  • removeSyncItem – If an item has been deleted on the device, and a similar one should be deleted from the data provider, DSS uses this to delete it
  • mergeSyncItems – If the module has been designed to resolve conflicting similar items from the device and data provider ends by merging them, DSS uses this to get that merged version as a step before sending the update to the device and data provider ends. (This method is available only if your PIMCalendarSyncSource extends MergeableSyncSource.)
  • commitSync – This is the next-to-last call DSS makes into a module for a sync. It calls it even if a SyncSourceException has been thrown by a previous call, which IMO is a design flaw since it doesn’t follow the traditional semantics of a ‘commit’; for example, if one plans to do all updates and deletions to the data provider via a batch, one would want to do that here — but that allows for loss of data integrity because a related update to the device might have failed.
  • endSync – Always the last call DSS makes into a module

If one wants to provide support for events and contacts using the SIF, VCalendar, and VCard formats, there are several ways to split up the work across modules. One could make a separate module for each combination, responsible for only one format of one kind of data, or have a single module that handles all types and formats. The major constraint on modules is that each can have only one auth Officer. While this constraint didn’t limit our design choices, we did happen to implement contacts and events in separate modules in separate source trees but where both modules would use the same officer code. Having separate trees had the unfortunate consequence of needing to copy/paste the officer code from one tree to the other, putting it in a different package, and configuring the two modules to use these different officer packages. Clearly, relying on copy/paste opens the door to maintenance problems; I recommend using a single source tree and single officer codebase if at all possible.

Putting a Module Together

In this section, we walk through the creation of a module to handle multiple data types and formats, where the data provider is a remote host rather than Funambol’s “webdemo” default.

First, find the source for DSS at Funambol’s downloads site, or via objectweb (e.g. http://cvs.forge.objectweb.org/cgi-bin/viewcvs.cgi/sync4j/funambol/modules/foundation/connector/src/main/java/com/funambol/foundation/engine/source/Attic/PIMCalendarSyncSource.java?hidecvsroot=0&search=None&hideattic=1&sortby=file&logsort=date&rev=1.18&content-type=text%2Fvnd.viewcvs-markup&diff_format=h). You’re looking for these files:

  • PIMCalendarSyncSource.java (and parent PIMSyncSource.java)
  • PIMCalendarManager.java (and parent PIMEntityManager.java)
  • init_schema.sql
  • SIFTaskSource.xml
  • VCalendarSource.xml
  • Funambol.xml
  • PersistentStoreManager.xml

Notice that PIMCalendarSyncSource implements the module API mentioned earlier by making calls into PIMCalendarManager, and PIMCalendarManager manipulates the co-installed dbms on behalf of the “webdemo” default webapp. You should hollow-out the method implementations of PIMCalendarManager and code them so they work for your existing data provider. I don’t have more to say about that part of the job.

The remainder of the work is configuring the module. Look in init_schema.sql at how the fnbl_sync_source table maps an incoming sourceUri (e.g. stask) to a bean file (e.g. SIFTaskSource.xml) that describes how to configure PIMCalendarSyncSource for that sourceUri. The key insight here is that every sync attempt triggers the creation of a new PIMCalendarSyncSource object, and that object manages state between the beginSync and endSync calls. By creating an object for every attempt, we can use the same Java class to handle different data types (events or tasks, even contacts) for different formats. Differences across data types and formats are largely hidden from you by the convenience methods in PIMCalendarSyncSource for marshalling and unmarshalling formats into Funambol data objects (e.g. Event, Task, and their common parent com.funambol.common.pim.calendar.CalendarContent). If you need to know the data type within your module code, you can use PIMCalendarSyncSource’s entityType member (or add your own member field and an entry in the bean files to populate it).

A module can support multiple data types and formats by adding an entry for each to the fnbl_sync_source table.

Be sure to make these changes:

  • Change the package and class name of the ‘object’ element in each bean file to match yours
  • Do the same for the ‘class’ attribute of the fnbl_sync_source_type table in init_schema.sql
  • Note that the values of the ‘config’ attribute of the fnbl_sync_source table aren’t filepaths in your source tree; instead, they reflect where the files will be unpacked from a zip after running bin/install-modules.sh. You need to check build.xml to make sure these files are pulled from the right place during the build.
  • Since you will be using your own solution for user acct management, you need to disable Funambol’s by providing a stub. In init_schema.sql, all entries in fnbl_sync_source_type should reference the stub class for the ‘admin_class’ attribute.

Next, look in Funambol.xml and notice the officer, store, and serverURI properties. The ‘serverURI’ value is probably ‘{serverURI}’, which indicates a placeholder that will be filled using install.properties when install-modules.sh is run; using placeholders is a pretty convenient way to get config into your module; you can define your own bean java and xml files, add your values to install.properties, and update install-module.xml to map those properties to placeholders in your bean xml file. You can also use a placeholder for the entire ‘officer’ property and put the xml in install.properties (which is helpful if you’re using different officer classes in different environments).

The ‘store’ property is important because it points to PersistentStoreManager.xml, which you will edit for your module. If your module will support fast/incremental sync, it needs its own db storage to keep track of the item id’s involved in the previous sync (aka “anchors”). For example, if the data provider provides a way of asking for all items changed since a certain time, but it doesn’t distinguish between which are new and which are updated, and doesn’t indicate any of the deleted ones, then you need to compare those id’s with the anchors: anchors that aren’t in the list from the data provider should be considered “deleted”; items from the provider that aren’t among the anchors should be considered “new”; all the rest can be considered “updated”.

To store and read anchors, you should create files create_schema.sql and drop_schema.sql (referenced in install-modules.xml) for creating and dropping the table(s) you need; if your module is listed in the modules-to-install property of install.properties when you run install-modules.sh, you will be prompted whether to recreate a table; answering ‘y’ will run drop_table.sql and then create_table.sql (so, you generally want to answer ‘n’ when installing unless you want to force all users to do slow syncs next time). To allow the module to read from and update the anchors, create java and xml bean code where the xml defines the SQL for inserting, updating, querying, and deleting. Add the bean xml filename to the list of such beans in PersistentStoreManager.xml.

Some of the files I’ve mentioned may not be in Funambol’s public source, and I’m sorry for that oversight. But they are helpful folks and I’m sure they would send you some samples.

Lessons Learned

Other than issues I’ve already mentioned, here are some issues you should be aware of up-front:

  1. There is no automated update process for getting the latest info about the world of devices. The sync portal needs this so it can offer support for the latest phones, and so it can keep up with changes in support for existing ones. You need to arrange with Funambol to be sent regular “phone pack” updates.
  2. There is no support for sending a message from the server to be displayed in the client. For errors, the best one can do is set a message in a thrown SyncSourceException, since the message will appear in the client log if it uses log level “error”.
  3. There is no way for a module to trigger a change from fast to slow sync in case, say, an error is found with anchor storage.
  4. The module API requires addItem to return the id that your storage will use for the item. This makes it hard if not impossible to include add’s with update’s and delete’s in a single batch during commitSync(); instead, you may need a synchronous network roundtrip for every call to addItem().
  5. It appears that the SIF Event content type used by Microsoft uses UTC-based times (e.g. 20080704T010000Z for 9amPT on July 4) for all values unless it’s an all-day event, in which case it uses YYY-MM-DD with no timezone indicator.  Funambol’s convert() in PIMCalendarSyncSource leaves these all-day values as-is instead of changing them to UTC format. I didn’t find any guiding principle about when UTC versus local time was used.
  6. The default dbms in the open source version of DSS is hypersonic. If you plan to use mysql, be sure to indicate your engine is InnoDB in your DDL scripts since Funambol’s dev wiki mentions there’s a risk of memory leaks without that.
  7. Since you’re using your own storage, make sure to remove the “webdemo” webapp (and associated db tables) so users don’t stumble across it by accident.
  8. When dealing with com.funambol.common.pim.calendar.RecurrencePattern, note that recurrence types with “NTH” in their name are for use when instance!=0, not when interval>0.
  9. Funambol’s Outlook plugin has a bug where if it is given an event that repeats every N years, it will change it to repeating yearly.
  10. Outlook has a bug where if it is given an event that repeats monthly, that’s timed/not-allday, and whose start time crosses a day boundary when converted to UTC (e.g. 4pm Pacific in summer becomes 1am UTC the next day), then Outlook will move it a day late (e.g. from Friday to Saturday). There is a similar problem when Outlook provides such an event, instead of consuming it.
  11. If an event is timed/not-allday but it has a duration of 24 hours, then the Outlook plugin will change it to an allday event, thereby losing start and end times.
  12. When a repeating event is created, synced, and then some individual dates on each end are modified or deleted (they must be different dates on each end), then on the next sync they will show as dupes. This is because Funambol’s default merge method has a bug…such changed dates are represented as an “exclusions list” in the RecurrencePattern obj, and merge should take the union of the device’s list and the data provider’s.
  13. Most devices don’t support multiple calendars, so Funambol has no special support for them, but your data provider may have many users who have these. As long as your module uses a concatenation of calendar id and event id as the full id given to DSS (to guarantee each item id that DSS has is unique within a user’s set of id’s), there should be no problem.
  14. It’s not feasible to host, say, a contacts module in one DSS and a calendar module in another DSS, and rely on sniffing to route http requests to the correct server. The problem is that the sourceUri is the one piece of info that would allow such decisions, but it’s embedded in the request payload, not the http headers.
  15. If a user did a manual sync at the same time that one of his devices happened to do an auto-sync, I believe there is no mechanism in DSS to detect this and block one of the requests, to avoid loss of data integrity for the user. For example, imagine there are similar events on device A, data provider B, and auto-syncing device C; while A and B are merging, C might update the event on B; when the merge of A and B is done and the update happens on B, it wipes out the info from C.
  16. If you use the carrier edition, be aware that your init_schema.sql isn’t the only file controlling what sourceUri’s the DSS thinks it supports. There are also portal/database/cared-coredb-mysql.sql and portal/database/cared-mysql.sql. Be sure to remove INSERT calls from these for sourceUri’s you won’t support, to ensure the user sees an error saying something like “Remote name not recognized” rather than a generic error.
  17. If you see error “Fatal error creating the PersistentStore object” in your log, a possible cause is having the wrong line endings in the config files of your s4j file. For example, if you build the s4j on a Windows machine and try to run it on a *nix machine, you are likely to see this error.
  18. Trivia item: The second param to the ICalendarParser constructor, a String, represents the device’s charset, not its timezone.

Community Mailing Lists

Good luck!

Print Friendly, PDF & Email

How to search for a string pattern in a directory tree in *nix

grep --include='FILEPATTERN' -rin SEARCHPATTERN *

Where:
FILEPATTERN is the file name pattern you want to match, for example 'h*' for all files that start with h
-r is recursive
i is ignore case for SEARCHPATTERN matching
n is print out the line number
SEARCHPATTERN is what you want to search
* is to include all files (which is usually what you use if you use --include)
Print Friendly, PDF & Email

How to avoid the error beep in MySQL client

Continuing today’s theme of avoiding ill-considered audio feedback in some desktop tools, the MySQL client plays a beep on errors, and one can’t avoid it even if volume is muted.

To avoid it, invoke the client with a –no-beep argument like this:

“C:Program FilesMySQLMySQL Server 5.0binmysql.exe” -u userid -p –no-beep

Print Friendly, PDF & Email

How to avoid the “breaking glass” sound in TortoiseCVS

When an error occurs in the TortoiseCVS client, it plays a “breaking glass” sound that can be pretty annoying. To avoid this, rename or delete C:Program FilesTortoiseCVSTortoiseCVSError.wav

Note that the error sound plays even if uses Preferences to set Progress Messages to “Really Quiet” (although I suspect this preference controls the verbosity of text feedback, not audio — a poor labelling choice).

Print Friendly, PDF & Email

Top 7 most common mistakes with Javascript syntax

Ok, my basis for saying “most common” is not at all scientific, just a gut sense of how many times I’ve seen 15 mins or more spent trying to find a bug that ended up being just a syntax error in one’s script. Tools like JSLint and Firebug are really helpful in general, but not with these issues. (I’ve heard Aptana should be, but I couldn’t get it to work and it kept crashing on me.)

  1. Spurious comma after the last entry in a JSON object string

    {name:’Fred’,visits:3,}

  2. Use of = instead of : in a JSON object string

    {name=‘Fred’}

  3. Misspelled function and object names

    encodeURICompoent

    onReadyStateChange instead of onreadystatechange

  4. Spurious parenthesis after a function call

    confirm(‘Proceed?’));

  5. Using parenthesis instead of braces for access within arrays and objects

    htsVisits(‘Fred’)

  6. Spurious : between keyword case and a switch value

    case: 1:

  7. Expecting “False” or new Boolean(“False”) to evaluate as true
Print Friendly, PDF & Email

WebDAV: IETF Standard for Collaborative Authoring on the Web

A comment on: Introduction to IETF WebDAV standard (IEEE Internet Computing, September/October, 1998)

WebDAV, or just DAV, is “Distributed Authoring and Versioning”, a protocol that extends HTTP to allow creating, editing, and managing versions of resources using URLs. DAV completes Tim Berners-Lee’s original vision of the web as not just a collection of read-only resources but of read/write ones.

The main features are:

  • The ability to define an access control list (ACL) for a remote web resource, to limit who can write to it.
  • The ability to place an exclusive lock (for serial sharing) or a shared lock (for simultaneous sharing) on a remote web resource, just before editing it.
  • The ability to get and set properties (metadata) on a remote resource, similar to the filename/creationDate/etc attributes of a file in a file system.
  • The ability to define resource collections similar to directories, and references similar to soft links.

Planned extensions to the protocol will define search and versioning should behave.

These features comprise a “network file system”, which on its own is not a new thing. But since this is a protocol, it’s platform-independent. Microsoft, Netscape, and Xerox have all contributed (and Office 2000 supports it), but no corporation dominates its direction.

On a practical note, you might wonder why not just use FTP. Well, that’s not secure. But you could use it with SSH. Yet, not all platforms and apps support SSH; DAV, on the other hand, leverages the security of HTTPS.

IMO, DAV is one of the core Internet technologies of the near future. There is a growing sense that email, documents, webpages/blogs/RSSfeeds, etc have to be tamed through a uniform interface for creating and sharing resources with people. DAV holds the promise of being a uniform underlying technology that could spark that uniform interface. And when such simplifications occur, creativity is freed up to discover new uses.

Print Friendly, PDF & Email

Debugging Javascript in IE when you don’t control the page

So everything works great from your dev server, but once deployed, a script problem is discovered. Even worse, it only happens in IE.

Something that worked for me was to install Fiddler for .Net 2.0. There’s a nice walkthrough WMV video (why do voices in walkthrough videos all sound like the famous Ruby one?). The video doesn’t say much that one couldn’t figure out from the UI, with one exception: The black bar at the lower right for setting breakpoint patterns. For example, enter “bpu” followed by a space and some substring of the filename you’d like to break on. (If “Capturing” isn’t already showing in the bottom left status bar, click there and it will begin recording.) When one visits the page of interest, Fiddler will suspend the network request and flash in the taskbar. A red ‘T‘ will show in the left panel for the breakpointed resource, and a red box will show in the right panel. Click on the yellow ‘Break on Response’ button, and if it shows “response is encoded” below that, double-click on that message. You should see a ‘Text View’ tab; click on it. Edit the resource as you like, and then click the green ‘Run to completion’ button. Note that Fiddler breakpoints even if the file is already in cache!

This allows for inserting JS alerts and such, but it seems it could also allow one to insert a script tag for FirebugLite, and then you’d be able to debug after page load, too.

The particular problem this helped with was: Our rich text editor (RTE) wouldn’t allow one to type in it (after the page load and as long as the page was in view). This usually happened only after the cache had been cleared. This pointed to a timing issue, and sure enough, the problem was that the RTE’s iframe wasn’t complete before we tried to enable design mode on it. This is the same issue I blogged about with IE’s createStyleSheet method, but in this case there was no script error indicated. Our code to handle this case had a typo in it — I had spelled “onreadystatechange” as “onReadyStateChange” as O’Reilly’s Dynamic HTML: The Definitive Reference spells it, which is a typographic convention for highlighting the words within handler names that will cause you grief if you follow the spelling literally. Use all lowercase!

Print Friendly, PDF & Email

IEDeveloperToolbar almost as useful as Firebug

I was just told that there’s an IE Developer Toolbar:
http://www.windowsmarketplace.com/details.aspx?view=info&itemid=2695980

At first glance, it provides a significant fraction of the utility of Firebug, such as showing DOM structure changes post-load. It also has a “Trace Style” feature, evidently for revealing the cascade of styles that apply to a particular element, but when I tried it all it did was open a window displaying my stylesheet.

It does not appear to support live editing of markup or styles.

Print Friendly, PDF & Email