LightSwitch timeouts and SessionState service

In terms of IIS, a LS app is just another web app, so all the same rules apply such as Forms Session cookies.  I had taken care to set session timeouts, but still was having timeouts at random times which left me confused; until I realized application pool restarts wipe out the session state on the server.  So you need a way to persist session state across AppPool restarts (and server restarts).  If you are using 3rd party Hoster, your app pool is normally shared across all sites on the server. So you should assume your app pool is restarting all the time for various reasons (configuration changes, memory pressure, maintence, etc)  The easiest way to store session state is the use the ASP.NET State Service.  Here is the process:

1) Start the ASP.NET State Service and change to automatic startup. Your hoster may already have it started.  Arvixe does for example.

2) Update your LS web.config in the ServerGenerated folder. Add or change the authentiation element and sessionState element using below as a guide.

3) Deploy your app again and browse to your application or  Hit F5 if already open to pull down new version and update session.
<system.web>

    <authentication mode=”Forms”>
      <forms name=”MyAppName” timeout=”1440″ />
    </authentication>
    <sessionState mode=”StateServer” cookieless=”false” timeout=”1440″ />

<system.web>

You can also view or change your application’s session state in IIS MMC in the Session State icon. It is best to add to your LS web.config as it will persist across deployments.

image

Hope that helps.
–William

Posted in C#, LightSwitch | Tagged , ,

LightSwitch and Slot number order for Auditions Sample

Create a junction table to map Auditions to People. The AuditionSlots table will include the SlotNumber (make Unique) and the Person and Audition (make Unique). This way, slot numbers are unique per audition. Change the slot numbers to reorder acts and save.

image

AuditionSlots table

image

Auditions Table

image

Posted in C#, LightSwitch | Tagged

Febco 765 Sprinkler Backflow Repair

Ok, first none technical post in a long time.  It is rare when you find something that is cheaper, better, and designed better then the original repair part.  This gave me some joy, so I felt it deserved a post for someone else.  If you have a Febco 765 Backflow on your house for your sprinkler system (as many do), don’t buy the Febco replacement Bonnet and Poppet kit as it is junk (the rest of the unit is good).  This Blue Heron replacement is 5 times better.  Better plastic and better design. DIY for about $30 bucks from SpinklerWarehouse.  A plumber or sprinkler guy will charge you $100-$200 for the repair and will probably not use this fine part.  Even if you don’t need one yet, I would buy this, replace current and keep old one as emergency spare.

FebcoPoppet

http://www.sprinklerwarehouse.com/Blue-Heron-Replacement-Kit-Febco-p/abr091011.htm

Posted in Uncategorized

Switch your lights with LightSwitch

LightOn

With a name like LightSwitch, you know someone had to do it eventually. Smile

Here is fun little project that combines Microsoft LightSwitch and a Microsoft Micro Framework controller to switch LEDs on and off.  Here is the hardware:

LSFritzing

  • FEZ Panda
  • Breadboard small
  • 2 LEDs, one red, one green
  • Jumper wire
  • 1 or 2 100 ohm resistors. Sharing a resistor here.

2011-06-13 14.08.17

And here is the LS screen to both control lights and see current light status:

LSLightScreen2

Below is the LS table that drives everything:

LSTable

Basically, it works as follows:

  • I hook into the tables Updating event.
  • Inside the event, I send a single line command to the NETMF device via SerialPort.
  • The NETMF device is listening on USB serial device in a loop reading lines and performs the on/off switching based on what light name is send in the command line.
  • Before leaving Updating event, I update the light status to on or off to reflect its new state.
  • After the Save, the screen reflects the new state information that was set inside the Updating event.
partial void LightStatusSet_Updating(LightStatus entity)
{
    SendLightCommand(entity);

    if (!entity.LastTurnOnTime.HasValue && entity.TurnOnNow)
    {
        // Turn on stopwatch.
        entity.LastTurnOnTime = DateTime.Now;
    }
    else if (entity.LastTurnOnTime.HasValue && ! entity.TurnOnNow)
    {
        // Turn off stopwatch.
        TimeSpan ts = (DateTime.Now - entity.LastTurnOnTime.Value);
        entity.HoursOn += ts.TotalHours;
        entity.LastTurnOnTime = null;
    }
}
private static void SendLightCommand(LightStatus entity)
{
    if (!entity.IsActive) return;
    if (port == null)
    {
        port = new SerialPort("com3");
        port.Open();
        Debug.WriteLine("Port opened. Send cmds.");
    }

    if (entity.TurnOnNow)
    {
        port.WriteLine(entity.Name + ",ON");
        entity.IsOn = true;
    }
    else
    {
        port.WriteLine(entity.Name + ",OFF");
        entity.IsOn = false;
    }
}

The device side is done same way. Just block reading lines from the SerialPort in a loop and handle the commands by name.  Here is the device code:

using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.USBClient;
using System.Text;

namespace FezPandaApp1
{
    public class Program
    {
        static OutputPort sysLed;
        static OutputPort led1;
        static OutputPort led2;

        public static void Main()
        {
            Debug.EnableGCMessages(false);
            sysLed = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);
            led1 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di6, false);
            led2 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di7, false);

            ReadComm();

            Debug.Print("Done.");
        }

        public static USBC_CDC StartCDC()
        {
            // Check debug interface. We don't do this check with CDC debugging port
            //if (Configuration.DebugInterface.GetCurrent() == Configuration.DebugInterface.Port.USB1)
            //    throw new InvalidOperationException("Current debug interface is USB. It must be changed to something else before proceeding. Refer to your platform user manual to change the debug interface.");

            // Start CDC
            Debug.Print("Hit Break all. Then Continue to Init CDC.");
            USBC_CDC cdc = USBClientController.StandardDevices.StartCDC_WithDebugging();

            // Send "Hello world!" to PC every second. (Append a new line too)
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes("Hello world!\r\n");

            int count = 10;
            while (count-->0)
            {
                Debug.Print("Sending on comm.");
                // Check if connected to PC
                if (USBClientController.GetState() != USBClientController.State.Running)
                {
                    Debug.Print("Waiting to connect to PC...");
                }
                else
                {
                    cdc.Write(bytes, 0, bytes.Length);
                }
                Thread.Sleep(500);
            }
            return cdc;
        }

        public static void ReadComm()
        {
            USBC_CDC port = StartCDC();
            port.ReadTimeout = -1;
            while (true)
            {
                string line = CDCReadLineEx(port, 512);
                bool result = HandleCommand(line);
                if (!result) break; // Exit cmd.
                //CDCWriteLine(port, line); // Write reply if needed.
            }
        }
        
        public static bool HandleCommand(string line)
        {
            string[] cmds = line.Split(',');
            if (cmds.Length != 2) return true;
            string cmd = cmds[0].Trim().ToLower();
            string arg1 = cmds[1].Trim().ToLower();

            switch (cmd)
            {
                case "sys":
                    if (arg1 == "on")
                        sysLed.Write(true);
                    else
                        sysLed.Write(false);
                    break;
                case "led1":
                    if (arg1 == "on")
                        led1.Write(true);
                    else
                        led1.Write(false);
                    break;
                case "led2":
                    if (arg1 == "on")
                        led2.Write(true);
                    else
                        led2.Write(false);
                    break;
                case "exit":
                    return false;
                default: // Ignore
                    break;
            }
            return true;
        }

        public static int CDCWriteLine(USBC_CDC port, string line)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(line+"\n");
            return port.Write(bytes, 0, bytes.Length);
        }

        public static string CDCReadLineEx(USBC_CDC sr, int bufLen)
        { 
            char[] readLineBuff = new char[bufLen];
            int curPos = 0;
            byte[] ba = new byte[1];
            while (true)
            {
                int read = sr.Read(ba, 0, 1);
                if (read <= 0) break;
                readLineBuff[curPos] = (char)ba[0];
                if (readLineBuff[curPos] == '\n')
                {
                    return new string(readLineBuff, 0, curPos);
                }
                curPos++;
            }

            if (curPos == 0) return null; // Null fix.
            return new string(readLineBuff, 0, curPos);
        }
    }
}

For this sample, we are just switching LEDs. But you could easily switch actual lights and other high power devices by adding Relays and/or MOSFETs to the setup.

Cool thing about using LightSwitch for this is it is already internet-ready and multi-user ready.  So deploy to the cloud and switch your lights over the internet.

So what if your LightSwitch server is hosted at a provider or not near your light sources?  Good news. You are covered there also. Instead of using a serial port, you can hook your NETMF device to Ethernet or wireless instead.  Do some port forwarding and/or open up your NAT at home and your LS server can send commands to your public facing NAT IP address which can forward to your FEZ.  You could also create a WCF RIA service on some box at home (or work) and talk to it from the LS server side.  You have many options with some imagination.  Just don’t open up your screen to the public if you don’t want your lights blinking on and off! Smile

Have fun and post blogs of your project !

--William Stacey

Posted in .Net Micro Framework, C#, LightSwitch | Tagged , , | 3 Comments

NETMF Get/Set Real Time Clock (RTC)

Just a short reminder post on how to get and set RTC.  The RTC is powered by VBatt pin and keeps the RTC ticking with the time after you set it once.  After you set it, then just read the time on boot and set the system clock.

private static DateTime SetDateTimeFromRTC()
{
    // RealTimeClock.SetTime(new DateTime(2011, 4, 22, 1, 1, 1, 0)); // Set once to set the RTC.
    DateTime dt = RealTimeClock.GetTime(); // Get RTC time.
    Utility.SetLocalTime(dt); // Set system clock.
    return dt;
}
Posted in .Net Micro Framework, C# | Tagged , , , | 1 Comment

FEZ firmware update helper

Just wanted a reminder post when I have to update FEZ with new firmware.

Update Fez Firmware
1) Hold LDR button then plug in USB.  New comm port should appear in devices (i.e. comm13)
2) Open TeraTerm
3) Erase current with E
4) Load new firmware with X from location (e.g. C:\Program Files (x86)\GHI Electronics\GHI NETMF v4.1 SDK\USBizi\Firmware)
5) Use XModem and 1K transfer.
6) Update your GHI references in your project(s) by removing them and adding them back. Create a screen snip of references before removing them to help remember which to add back.

Can also use MFDeploy to verify version before and after or just to check what level.

Posted in .Net Micro Framework, C#, FEZ | Tagged ,

NETMF Servo classes (PWM and Software versions)

Just posting some servo classes.  One for hardware PWM control and one for software PWM using OutputCompare. Never know when you may need.

using System;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;

namespace MicroFezRobot
{
    public class ServoHardPWM : IServo
    {
        readonly PWM pwm;
        readonly uint periodUs;     // Number of us in period.
        readonly uint periodNs;     // Number of ns in period.
        readonly uint lowDegree;    // Low degree of servo; 0 default.
        readonly uint highDegree;   // High degree of servo; 180 default.
        uint lowUs = 690;           // microsecond (us) range. Find your specific values with servo range testing.
        uint highUs = 2422;         // microsecond (us) range.
        bool invert;                // Invert/reverse rotation.
        DateTime lastChanged;

        public ServoHardPWM(FEZ_Pin.PWM pin, uint periodUs=20000, uint lowUs=1000, uint highUs=2000, uint lowDegree=0, uint highDegree=180)
        {
            this.periodUs = periodUs;
            this.periodNs = this.periodUs * 1000;
            this.lowUs = lowUs;
            this.highUs = highUs;
            this.lowDegree = lowDegree;
            this.highDegree = highDegree;
            this.pwm = new PWM((PWM.Pin)pin);
            pwm.Set(false);
            this.lastChanged = DateTime.Now;
        }

        /// <summary>
        /// Gets or sets value to invert direction.
        /// </summary>
        public bool Invert
        {
            get { return invert; }
            set { this.invert = value; }
        }

        /// <summary>
        /// Gets number of microseconds (us) in the period.
        /// </summary>
        public uint Period
        {
            get { return periodUs / 1000; }
        }
        
        /// <summary>
        /// Gets or sets number of microseconds (us) in low servo range.
        /// </summary>
        public uint LowRange
        {
            get { return this.lowUs; }
            set { this.lowUs = value; }
        }

        /// <summary>
        /// Gets or sets number of microseconds (us) in high servo range.
        /// </summary>
        public uint HighRange
        {
            get { return this.highUs; }
            set { this.highUs = value; }
        }

        /// <summary>
        /// Gets datetime position was last changed.
        /// </summary>
        public DateTime LastChanged
        {
            get { return this.lastChanged; }
        }

        /// <summary>
        /// Sets current servo angle degree.
        /// </summary>
        /// <param name="degree">Degree to set. (i.e. 0-180)</param>
        public void SetDegree(uint degree)
        {
            if (degree < lowDegree || degree > highDegree)
                throw new ArgumentOutOfRangeException("angleDegree");

            uint posUs = ScaleRange(degree, lowDegree, highDegree, lowUs, highUs);
            SetPosition(posUs);
        }

        /// <summary>
        /// Sets current servo position.
        /// </summary>
        /// <param name="positionUs">High time in microseconds.</param>
        public void SetPosition(uint positionUs)
        {
            if (invert)
                positionUs = (highUs - positionUs) + lowUs;

            uint posNs = positionUs * 1000; // convert us to ns as SetPulse uses ns scale.
            pwm.SetPulse(periodNs, posNs);
            this.lastChanged = DateTime.Now;
        }

        /// <summary>
        /// Stops holding servo at current position by setting PWM low.
        /// </summary>
        public void Stop()
        {
            pwm.Set(false);
        }

        /// <summary>
        /// Dispose servo instance.
        /// </summary>
        public void Dispose()
        {
            // Try to stop servo clean on a pulse low.
            Stop();
            pwm.Dispose();
        }

        private static uint ScaleRange(uint oldValue, uint oldMin, uint oldMax, uint newMin, uint newMax)
        {
            return ((oldValue - oldMin) * (newMax - newMin) / (oldMax - oldMin)) + newMin;
        }
    }
}

using System;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
using Microsoft.SPOT.Hardware;

namespace MicroFezRobot
{
    interface IServo : IDisposable
    {
        bool Invert { get; set; }
        uint Period { get; }
        uint LowRange { get; set; }
        uint HighRange { get; set; }
        DateTime LastChanged { get; }
        void SetDegree(uint angleDegree);
        void SetPosition(uint position);
        void Stop();
    }

    public class ServoSoftPWM : IServo
    {
        readonly OutputCompare oc;
        readonly uint periodUs;     // Normally 20,000us (i.e. 20ms)
        readonly uint lowDegree;    // Low degree of servo; 0 default.
        readonly uint highDegree;   // High degree of servo; 180 default.
        readonly uint[] timings;    // Used for setting OC timings.
        uint lowUs;                 // Small servo (e.g. 690)
        uint highUs;                // Small servo (e.g. 2422)
        bool invert;                // Invert servo direction control.
        DateTime lastChanged;

        public ServoSoftPWM(FEZ_Pin.Digital pin, uint periodUs=20000, uint lowUs=1000, uint highUs=2000, uint lowDegree=0, uint highDegree=180)
        {
            this.oc = new OutputCompare((Cpu.Pin)pin, true, 2);
            this.timings = new uint[2];
            this.periodUs = periodUs;
            this.lowUs = lowUs;
            this.highUs = highUs;
            this.lowDegree = lowDegree;
            this.highDegree = highDegree;
            this.lastChanged = DateTime.Now;
        }

        /// <summary>
        /// Gets or sets a value to invert the servo direction.
        /// </summary>
        public bool Invert
        {
            get { return this.invert; }
            set { this.invert = value; }
        }

        /// <summary>
        /// Gets the period in microseconds.
        /// </summary>
        public uint Period
        {
            get { return this.periodUs; }
        }

        /// <summary>
        /// Gets or sets the low servo range in microseconds.
        /// </summary>
        public uint LowRange
        {
            get { return this.lowUs; }
            set { this.lowUs = value; }
        }

        /// <summary>
        /// Gets or sets the high servo range in microseconds.
        /// </summary>
        public uint HighRange
        {
            get { return this.highUs; }
            set { this.highUs = value; }
        }

        /// <summary>
        /// Gets datetime of last position change.
        /// </summary>
        public DateTime LastChanged
        {
            get { return this.lastChanged; }
        }

        /// <summary>
        /// Sets the current servo angle in degrees.
        /// </summary>
        /// <param name="degree">Degree angle to set.</param>
        public void SetDegree(uint degree)
        {
            if (degree < lowDegree || degree > highDegree)
                throw new ArgumentOutOfRangeException("angleDegree");

            uint highTime = ScaleRange(degree, lowDegree, highDegree, lowUs, highUs);
            SetPosition(highTime);
        }

        /// <summary>
        /// Sets the current position of the servo.
        /// </summary>
        /// <param name="positionUs">Position in microseconds</param>
        public void SetPosition(uint positionUs)
        {
            if (positionUs < lowUs || positionUs > highUs)
                throw new ArgumentOutOfRangeException("positionUs");

            if (invert)
                positionUs = (highUs - positionUs) + lowUs;

            // OutputCompare uses microsecond (us) scale.
            timings[0] = positionUs;
            timings[1] = periodUs - positionUs;
            oc.Set(true, timings, 0, 2, true);
            this.lastChanged = DateTime.Now;
        }

        /// <summary>
        /// Stops holding servo at current position by setting PWM low.
        /// </summary>
        public void Stop()
        {
            oc.Set(false);
        }

        /// <summary>
        /// Dispose servo instance.
        /// </summary>
        public void Dispose()
        {
            Stop();
            oc.Dispose();
        }

        private static uint ScaleRange(uint value, uint oldMin, uint oldMax, uint newMin, uint newMax)
        {
            uint v = ((value - oldMin) * (newMax - newMin) / (oldMax - oldMin)) + newMin; // same good.
            return v;
        }
    }
}

-William

Posted in .Net Micro Framework, C#, FEZ, Motors, Servo | Tagged , , ,