From: <Ba...@us...> - 2012-01-17 23:06:28
|
Revision: 4408 http://mp-plugins.svn.sourceforge.net/mp-plugins/?rev=4408&view=rev Author: BartEv Date: 2012-01-17 23:06:18 +0000 (Tue, 17 Jan 2012) Log Message: ----------- Improved error handling Modified Paths: -------------- trunk/plugins/VeraControl/DeviceCam.cs trunk/plugins/VeraControl/DeviceDimmer.cs trunk/plugins/VeraControl/DeviceDoorlock.cs trunk/plugins/VeraControl/DeviceGeneric.cs trunk/plugins/VeraControl/DeviceSecurity.cs trunk/plugins/VeraControl/DeviceSprinkler.cs trunk/plugins/VeraControl/DeviceSwitch.cs trunk/plugins/VeraControl/DeviceSystem.cs trunk/plugins/VeraControl/DeviceThermostat.cs trunk/plugins/VeraControl/DialogDeviceControl.cs trunk/plugins/VeraControl/DialogSceneControl.cs trunk/plugins/VeraControl/Scene.cs trunk/plugins/VeraControl/VeraCommunication.cs trunk/plugins/VeraControl/VeraControl.cs trunk/plugins/VeraControl/VeraControl.csproj trunk/plugins/VeraControl/VeraHelper.cs trunk/plugins/VeraControl/skin/Default/VeraDialogDeviceControl.xml Added Paths: ----------- trunk/plugins/VeraControl/BaseDevice.cs Added: trunk/plugins/VeraControl/BaseDevice.cs =================================================================== --- trunk/plugins/VeraControl/BaseDevice.cs (rev 0) +++ trunk/plugins/VeraControl/BaseDevice.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -0,0 +1,175 @@ +/* + * Created by SharpDevelop. + * User: Bart + * Date: 17-1-2012 + * Time: 19:12 + * + * Copyright: 2012 GPL - Bart Eversdijk + * MediaPort plugin - MicasaVerde (TM) Vera Controller + * E-mail: ba...@ev... + */ +using System; +using System.Xml; + +namespace VeraControl.Properties +{ + /// <summary> + /// Description of BaseDevice. + /// </summary> + public class BaseDevice + { + public long m_lLastUpdate = 0; + public long m_lLastPendingUpdate = 0; + public bool m_bScreenUpdateRequired = false; + private string m_sName = "unknown device"; + private int m_iId = 0; + private int m_iRoom = 0; + + // not connected (-2), none (-1), pending (0,1,5,6), success(4), error (2,3) + private DevState m_dsState = DevState.NONE; + private string m_sComment = ""; // red(error), green(success) or blue(pending) - icon/text + + public VeraHelper helper = VeraHelper.Instance; + public VeraCommunication vera = VeraCommunication.Instance; + + public BaseDevice(XmlNode xn) + { + if (xn != null) + { + update(xn); + } + } + + /// <summary> + /// Process Vera update information + /// </summary> + public virtual bool update(XmlNode xn) + { + m_sName = helper.getAttrAsString(xn, "name", m_sName); + m_iId = helper.getAttrAsInt (xn, "id", m_iId); + m_iRoom = helper.getAttrAsInt (xn, "room", m_iRoom); + + string temp_sComment = helper.getAttrAsString(xn, "comment", m_sComment ); + DevState temp_dsState = helper.toDevState(helper.getAttrAsInt(xn, "state", -1)); + if (m_dsState != DevState.PENDING || temp_dsState != DevState.NONE || (temp_dsState == DevState.NONE && ((m_lLastPendingUpdate / TimeSpan.TicksPerSecond ) < (DateTime.Now.Ticks / TimeSpan.TicksPerSecond)))) + { // If state was set to pending next update should contain a new state or still pending - so do not clear pending flag for at least 10 seconds + m_sComment = temp_sComment; + m_dsState = temp_dsState; + } + if (m_iId == 0) + { + // void device no further processing needed + return false; + } + + // Set update flag + m_bScreenUpdateRequired = true; + m_lLastUpdate = DateTime.Now.Ticks; + return true; + } + + /// <summary> + /// Returns the id of this device + /// </summary> + public int id + { + get { return m_iId; } + set { } + } + + /// <summary> + /// Returns the name of this device + /// </summary> + public string name + { + get { return m_sName; } + set { } + } + + /// <summary> + /// Returns true when this device is associated with the given room + /// </summary> + public bool inRoom(int id) + { + return (m_iRoom == id); + } + + /// <summary> + /// Return the room is this device is associated with + /// </summary> + public int room + { + get { return m_iRoom; } + set { m_iRoom = value; } + } + + /// <summary> + /// Return the communications state for this device + /// </summary> + public DevState commstate + { + get { return m_dsState; } + set { } + } + + /// <summary> + /// Return the comment as reported by Vera for this device + /// </summary> + public string comment + { + get { return (commstate != DevState.NONE ? m_sComment : ""); } + set { } + } + + /// <summary> + /// Set virtual device state to pending request + /// </summary> + public void reportPendingRequest() + { + m_dsState = DevState.PENDING; + m_sComment = "Sending command..."; + m_bScreenUpdateRequired = true; + m_lLastUpdate = DateTime.Now.Ticks; + m_lLastPendingUpdate = m_lLastUpdate; + } + + /// <summary> + /// Callback function for Ansync Web Client call on to report errors... + /// </summary> + public void reportRequestError(string message) + { + m_dsState = DevState.COMMAND_ERROR; + m_sComment = message; + m_bScreenUpdateRequired = true; + m_lLastUpdate = DateTime.Now.Ticks; + } + + public void clearCommState() + { + m_dsState = DevState.NONE; + } + /// <summary> + /// True when an update was processed after the give time stamp + /// </summary> + public virtual bool newUpdateSince(long lTimePreviousCheck) + { + return (lTimePreviousCheck <= m_lLastUpdate); + } + + /// <summary> + /// Invoking this method will clear the update ready flag -> so caller need to handle the screen update + /// </summary> + public virtual bool newScreenUpdateWaitingAndClearFlag( ) + { + bool b = m_bScreenUpdateRequired; + m_bScreenUpdateRequired = false; + return b; + } + + public override string ToString() + { + return name; + } + + } +} Modified: trunk/plugins/VeraControl/DeviceCam.cs =================================================================== --- trunk/plugins/VeraControl/DeviceCam.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceCam.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -15,7 +15,7 @@ /// Description of DeviceCam. /// </summary> public class DeviceCam : DeviceGeneric - { + { // TODO: add IP-cam control buttons private string m_sIp = "127.0.0.1"; private string m_sUrl = "/"; private string m_sStream = ""; @@ -54,7 +54,7 @@ private bool refreshDelayPassed(long lastcheck) { - return ((helper.getSecondsSince1970() - refreshRate) > (lastcheck / 10000000)); + return ((helper.getSecondsSince1970() - refreshRate) > (lastcheck / TimeSpan.TicksPerSecond)); } public override string getIconName() Modified: trunk/plugins/VeraControl/DeviceDimmer.cs =================================================================== --- trunk/plugins/VeraControl/DeviceDimmer.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceDimmer.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -64,13 +64,14 @@ } else { if (newValue < 0) { newValue = 0; } } - if ((id > 0) && (newValue != m_iLevel)) // Only send when a valid ID is found - { + if (id > 0) // Only send when a valid ID is found + { + reportPendingRequest(); // Do something with vera string cmd = "?id=lu_action&DeviceNum="+id.ToString()+ "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget" + "&newLoadlevelTarget="+value; - vera.doVeraRequest(cmd); + vera.doVeraCommandRequest(cmd, reportRequestError); } m_iLevel = newValue; } Modified: trunk/plugins/VeraControl/DeviceDoorlock.cs =================================================================== --- trunk/plugins/VeraControl/DeviceDoorlock.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceDoorlock.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -41,13 +41,13 @@ set { if (id > 0) // Only send when a valid ID is found { + reportPendingRequest(); // Do something with vera string cmd = "?id=lu_action&DeviceNum="+id.ToString()+ "&serviceId=urn:micasaverde-com:serviceId:DoorLock1&action=SetTarget" + "&newTargetValue="+(value ? "1" : "0"); - vera.doVeraRequest(cmd); + vera.doVeraCommandRequest(cmd, reportRequestError); } - m_bStatus = value; } } Modified: trunk/plugins/VeraControl/DeviceGeneric.cs =================================================================== --- trunk/plugins/VeraControl/DeviceGeneric.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceGeneric.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -14,29 +14,15 @@ namespace VeraControl.Properties { - - /// <summary> /// Description of DeviceGeneric. /// </summary> - public class DeviceGeneric + public class DeviceGeneric : BaseDevice { - public long m_lLastUpdate = 0; - public bool m_bScreenUpdateRequired = false; - private string m_sName = "unknown device"; - private int m_iId = 0; private string m_sAltId = ""; private int m_iCategory = 0; - private int m_iRoom = 0; - // not connected (-2), none (-1), pending (0,1,5,6), success(4), error (2,3) - private DevState m_dsState = DevState.NONE; - private string m_sComment = ""; // red(error), green(success) or blue(pending) - icon/text - - public VeraHelper helper = VeraHelper.Instance; - public VeraCommunication vera = VeraCommunication.Instance; - - public DeviceGeneric(XmlNode xn) + public DeviceGeneric(XmlNode xn): base (xn) { if (xn != null) { @@ -44,97 +30,43 @@ } } - public virtual bool update(XmlNode xn) + public override bool update(XmlNode xn) { - m_sName = helper.getAttrAsString(xn, "name", m_sName); - m_iId = helper.getAttrAsInt (xn, "id", m_iId); m_sAltId = helper.getAttrAsString(xn, "altid", m_sAltId); m_iCategory = helper.getAttrAsInt (xn, "category", m_iCategory); - m_iRoom = helper.getAttrAsInt (xn, "room", m_iRoom); - m_sComment = helper.getAttrAsString(xn, "comment", m_sComment ); - m_dsState = helper.toDevState(helper.getAttrAsInt(xn, "state", -1)); - - if (m_iId == 0) + bool b = base.update(xn); + // Make sure the room exists + if (room == 0 || !vera.status.isRoomFound(room)) { - // void device no further processing needed - return false; - } - // Make sure room exists - if (m_iRoom == 0 || !vera.status.isRoomFound(m_iRoom)) - { if (!vera.status.isRoomFound(0)) { // create dummy room to attach to vera.rooms.Add(new Room(null)); } - m_iRoom = 0; + room = 0; } - - // Set update flag - m_bScreenUpdateRequired = true; - m_lLastUpdate = DateTime.Now.Ticks; - - return true; + + return b; } - - public int id - { - get { return m_iId; } - set { } - } - + public string altid { get { return m_sAltId; } set { } } - - public string name - { - get { return m_sName; } - set { } - } - + public int category { get { return m_iCategory; } set { } } - - public bool inRoom(int id) - { - return (m_iRoom == id); - } - public int room - { - get { return m_iRoom; } - set { } - } - - public override string ToString() - { - return name; - } - public virtual bool isControllable { get { return false; } set { } } - public virtual DevState commstate - { - get { return m_dsState; } - set { } - } - - public virtual string comment - { - get { return (commstate != DevState.NONE ? m_sComment : ""); } - set { } - } - public virtual bool status { get { return false; } @@ -183,18 +115,5 @@ { return new string [] {"Off", "On"}; } - - public virtual bool newScreenUpdateWaitingAndClearFlag( ) - { - // Invoking this method will clear the update ready flag -> so caller need to handle the update - bool b = m_bScreenUpdateRequired; - m_bScreenUpdateRequired = false; - return b; - } - - public virtual bool newUpdateSince(long lTimePreviousCheck) - { - return (lTimePreviousCheck <= m_lLastUpdate); - } } } Modified: trunk/plugins/VeraControl/DeviceSecurity.cs =================================================================== --- trunk/plugins/VeraControl/DeviceSecurity.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceSecurity.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -43,13 +43,13 @@ set { if (id > 0) // Only send when a valid ID is found { + reportPendingRequest(); // Do something with vera string cmd = "?id=lu_action&DeviceNum="+id.ToString()+ "&serviceId=urn:micasaverde-com:serviceId:SecuritySensor1&action=SetArmed" + "&newArmedValue=" + (value ? "1" : "0"); - vera.doVeraRequest(cmd); + vera.doVeraCommandRequest(cmd, reportRequestError); } - m_bArmed = value; } } Modified: trunk/plugins/VeraControl/DeviceSprinkler.cs =================================================================== --- trunk/plugins/VeraControl/DeviceSprinkler.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceSprinkler.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -49,13 +49,13 @@ set { if (id > 0) // Only send when a valid ID is found { + reportPendingRequest(); // Do something with vera string cmd = "?id=lu_action&DeviceNum="+id.ToString()+ "&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget" + "&newTargetValue="+(value ? "1" : "0"); - vera.doVeraRequest(cmd); + vera.doVeraCommandRequest(cmd, reportRequestError); } - m_bStatus = value; } } @@ -71,13 +71,13 @@ set { if (id > 0) // Only send when a valid ID is found { + reportPendingRequest(); // Do something with vera string cmd = "?id=lu_action&DeviceNum="+id.ToString()+ "&serviceId=urn:upnp-micasaverde-com:serviceId:Sprinkler1&action=" + (value == "Auto" ? "SetModeAuto" : (value == "Block" ? "SetModeBlock" : "SetModeManual")); - vera.doVeraRequest(cmd); + vera.doVeraCommandRequest(cmd, reportRequestError); } - m_sMode = value; } } Modified: trunk/plugins/VeraControl/DeviceSwitch.cs =================================================================== --- trunk/plugins/VeraControl/DeviceSwitch.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceSwitch.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -4,8 +4,8 @@ * Date: 22-12-2011 * Time: 14:25 * - * Copyright: 2012 GPL - Bart Eversdijk - * MediaPort plugin - MicasaVerde (TM) Vera Controller + * Copyright: 2012 GPL - Bart Eversdijk + * MediaPort plugin - MicasaVerde (TM) Vera Controller * E-mail: ba...@ev... */ using System; @@ -22,7 +22,7 @@ private string m_sWatt = "-"; private string m_sKwh = "-"; - public DeviceSwitch( XmlNode xn ): base (xn) + public DeviceSwitch( XmlNode xn ): base (xn) { if (xn != null) { @@ -30,13 +30,13 @@ } } - public override bool update(XmlNode xn) + public override bool update(XmlNode xn) { m_bStatus = helper.getAttrAsBool (xn, "status", m_bStatus); m_sWatt = helper.getAttrAsString(xn, "watts", m_sWatt); m_sKwh = helper.getAttrAsString(xn, "kwh", m_sKwh); - return base.update(xn); + return base.update(xn); } public string watts @@ -48,16 +48,16 @@ public override bool status { get { return m_bStatus; } - set { - if (id > 0) // Only send when a valid ID is found - { - // Do something with vera - string cmd = "?id=lu_action&DeviceNum="+id.ToString()+ - "&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget" + - "&newTargetValue="+(value ? "1" : "0"); - vera.doVeraRequest(cmd); - } - m_bStatus = value; + set { + if (id > 0) // Only send when a valid ID is found + { + reportPendingRequest(); + // Do something with vera + string cmd = "?id=lu_action&DeviceNum="+id.ToString()+ + "&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget" + + "&newTargetValue="+(value ? "1" : "0"); + vera.doVeraCommandRequest(cmd, reportRequestError); + } } } Modified: trunk/plugins/VeraControl/DeviceSystem.cs =================================================================== --- trunk/plugins/VeraControl/DeviceSystem.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceSystem.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -148,6 +148,14 @@ m_lLastUpdate = DateTime.Now.Ticks; } + public void reportCommandError( string errmsg ) + { + m_dsVeraState = DevState.COMMAND_ERROR; + m_sComment = errmsg; + m_bScreenUpdateRequired = true; + m_lLastUpdate = DateTime.Now.Ticks; + } + public void clearConnectionError( ) { m_dsVeraState = DevState.NONE; Modified: trunk/plugins/VeraControl/DeviceThermostat.cs =================================================================== --- trunk/plugins/VeraControl/DeviceThermostat.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DeviceThermostat.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -60,14 +60,14 @@ set { if (id > 0) // Only send when a valid ID is found { + reportPendingRequest(); // Do something with vera string cmd = "?id=lu_action&DeviceNum="+id.ToString()+ "&serviceId=urn:upnp-org:serviceId:HVAC_UserOperatingMode1&action=SetModeTarget" + "&NewModeTarget="+(value == "Off" ? "Off" : (value == "Cool" ? "CoolOn" : (value == "Heat" ? "HeatOn" : "AutoChangeOver")) ); - vera.doVeraRequest(cmd); + vera.doVeraCommandRequest(cmd, reportRequestError); } - m_sMode = value; } } Modified: trunk/plugins/VeraControl/DialogDeviceControl.cs =================================================================== --- trunk/plugins/VeraControl/DialogDeviceControl.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DialogDeviceControl.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -46,9 +46,12 @@ [SkinControl(30)] protected GUIImage cmtImage = null; [SkinControlAttribute(31)] protected GUILabelControl comment=null; - VeraHelper helper = new VeraHelper(); - private DeviceGeneric myDev = null; - private long m_iLastUpdate = 0; + private VeraHelper helper = new VeraHelper(); + private DeviceGeneric myDev = null; + private long m_iLastUpdate = 0; + private bool m_bLevelUpdatePending = false; + private long m_lLastLevelUpdate = 0; + private int m_iDesiredLevel = 0; public DialogDeviceControl() { @@ -60,7 +63,6 @@ bool bResult = Load(GUIGraphicsContext.Skin + @"\VeraDialogDeviceControl.xml"); return bResult; } - public void InitDialog(string strLine, DeviceGeneric dev) { @@ -75,7 +77,7 @@ { btnClose.SetNavigation(2,2,2,2); } - + updateStatus(); } @@ -96,8 +98,8 @@ { SetText(myDev.name, myDev.getStatusText(), myDev.getExtraText() ); SetActiveBut((myDev.status ? 1 : 0), (myDev.mode == "Auto" ? 0 : - (myDev.mode == "CoolOn" || myDev.mode == "Cool" ? 1 : - (myDev.mode == "HeatOn" || myDev.mode == "Heat" ? 2 : 3) ))); + (myDev.mode == "CoolOn" || myDev.mode == "Cool" ? 1 : + (myDev.mode == "HeatOn" || myDev.mode == "Heat" ? 2 : 3) ))); } else { @@ -105,7 +107,10 @@ SetActiveBut(myDev.status ? 1 : 0, -1); } SetButtons(myDev.getCommands()); - SetSlider(myDev.level, myDev.maxLevel); + if (!m_bLevelUpdatePending) + { + SetSlider(myDev.level, myDev.maxLevel); + } } else { @@ -120,52 +125,32 @@ m_iLastUpdate = DateTime.Now.Ticks; } - protected override void OnClicked(int controlId, GUIControl control, Action.ActionType actionType) { - if (control == btnLeft) - { - myDev.level = myDev.minLevel; - SetSlider( myDev.level, myDev.maxLevel ); - } - - if (control == btnRight) - { - myDev.level = myDev.maxLevel; - SetSlider( myDev.level, myDev.maxLevel ); - } - - if (control == btnMode1) - { - myDev.mode = btnMode1.Label; - SetActiveBut(-1, 0); - } - if (control == btnMode2) - { - myDev.mode = btnMode2.Label; - SetActiveBut(-1, 1); - } - if (control == btnMode3) - { - myDev.mode = btnMode3.Label; - SetActiveBut(-1, 2); - } - - if (control == slider) - { - myDev.level = slider.IntValue; - } - - // update button high lighting - SetActiveBut( (slider.IntValue > 0 ? 1 : 0), -1); - - // update icon - SetImage("Vera\\" + myDev.getIconName() + ".png"); - - // Back to the text button to switch from image view - if (control == btnClose) - { + if (control == btnClose) { PageDestroy(); + } else { + if (control == btnLeft) { + myDev.level = myDev.minLevel; + } + if (control == btnRight) { + myDev.level = myDev.maxLevel; + } + if (control == btnMode1) { + myDev.mode = btnMode1.Label; + } + if (control == btnMode2) { + myDev.mode = btnMode2.Label; + } + if (control == btnMode3) { + myDev.mode = btnMode3.Label; + } + if (control == slider) { + // Do something with fast repeating level changes.... slow down communications + m_bLevelUpdatePending = true; + m_iDesiredLevel = slider.IntValue; + SliderDebouncer(); + } } base.OnClicked(controlId, control, actionType); } @@ -197,9 +182,23 @@ } } + public void SliderDebouncer() + { + if (m_lLastLevelUpdate < DateTime.Now.Ticks) + { // If minimum update delay (2 sec) has been passed + if (m_bLevelUpdatePending && myDev.level != m_iDesiredLevel) + { + myDev.level = m_iDesiredLevel; + slider.IntValue = m_iDesiredLevel; + m_lLastLevelUpdate = DateTime.Now.Ticks + (TimeSpan.TicksPerSecond * 2); + } + m_bLevelUpdatePending = false; + } + } + public void SetSlider(int iVal, int iMaxval) { - if (iVal >= 0) + if ((iVal >= 0) && !m_bLevelUpdatePending) { slider.SetRange(0, iMaxval); slider.IntValue = iVal; @@ -276,8 +275,8 @@ if (myDev.newUpdateSince(m_iLastUpdate)) { updateStatus(); + SliderDebouncer(); } - base.Render(timePassed); } } Modified: trunk/plugins/VeraControl/DialogSceneControl.cs =================================================================== --- trunk/plugins/VeraControl/DialogSceneControl.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/DialogSceneControl.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -80,9 +80,7 @@ if (control == btnRight) { if (myScene.id != 0) { - comment.Label = "Running..."; myScene.run(); - } } Modified: trunk/plugins/VeraControl/Scene.cs =================================================================== --- trunk/plugins/VeraControl/Scene.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/Scene.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -17,116 +17,62 @@ /// <summary> /// Description of Scene. /// </summary> - public class Scene + public class Scene : BaseDevice { - public Scene(XmlNode xn) + public Scene(XmlNode xn): base (xn) { if (xn != null) { update(xn); } } - public VeraHelper helper = VeraHelper.Instance; - private bool m_bScreenUpdateRequired = false; - private string m_sName = "unknown scene"; - private int m_iId = 0; private bool m_bActive = false; - private int m_iRoom = 0; - private long m_lLastUpdate = 0; - - // not connected (-2), none (-1), pending (0,1,5,6), success(4), error (2,3) - private string m_sComment = ""; // red(error), green(success) or blue(pending) - icon/text - private DevState m_dsState = DevState.NONE; - - public bool update(XmlNode xn) + public override bool update(XmlNode xn) { - m_sName = helper.getAttrAsString(xn, "name", m_sName); - m_iId = helper.getAttrAsInt (xn, "id", m_iId); - m_iRoom = helper.getAttrAsInt (xn, "room", m_iRoom); - m_bActive = helper.getAttrAsBool (xn, "active", m_bActive); + m_bActive = helper.getAttrAsBool(xn, "active", m_bActive); + bool b = base.update(xn); - m_sComment = helper.getAttrAsString(xn, "comment", m_sComment ); - m_dsState = helper.toDevState(helper.getAttrAsInt(xn, "state", -1)); - - // Set update reqired flag - m_lLastUpdate = DateTime.Now.Ticks; - m_bScreenUpdateRequired = true; - return true; + // Make sure the room exists or is 0 + if (room != 0 && !vera.status.isRoomFound(room)) + { + if (!vera.status.isRoomFound(0)) + { // create dummy room to attach to + vera.rooms.Add(new Room(null)); + } + room = 0; + } + return b; } - public int id - { - get { return m_iId; } - set { } - } - - public string name - { - get { return m_sName; } - set { } - } - - public virtual DevState commstate - { - get { return m_dsState; } - set { } - } - public virtual string comment - { - get { return (commstate != DevState.NONE ? m_sComment : ""); } - set { } - } - public bool isActive() { return m_bActive; } - public bool inRoom(int id) + public void run() { - return (m_iRoom == id); - } - - public int room - { - get { return m_iRoom; } - set { } - } - - public override string ToString() - { - return name; - } - - public string run() - { if (id == 0) { - return "Unknown scene"; + vera.status.system.reportCommandError("Unknown scene"); + m_bScreenUpdateRequired = true; } - VeraCommunication vera = VeraCommunication.Instance; + reportPendingRequest(); string cmd = "?id=lu_action&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunScene&SceneNum="+id; - return vera.doVeraRequest(cmd); + vera.doVeraCommandRequest(cmd, reportRequestError); } - public bool newScreenUpdateWaitingAndClearFlag( ) + public override bool newScreenUpdateWaitingAndClearFlag( ) { - // Invoking this method will clear the update ready flag -> so caller need to handle the update - bool b = m_bScreenUpdateRequired; - m_bScreenUpdateRequired = false; - if (m_dsState != DevState.NONE && (m_lLastUpdate < (DateTime.Now.Ticks - (10 * 10000000)))) + // Scenes are not reported Done by Vera so the will time out... + bool b = base.newScreenUpdateWaitingAndClearFlag(); + if (commstate != DevState.NONE && (m_lLastUpdate < (DateTime.Now.Ticks - (10 * 10000000)))) { - m_dsState = DevState.NONE; + clearCommState(); return true; } return b; } - - public virtual bool newUpdateSince(long lTimePreviousCheck) - { - return (lTimePreviousCheck <= m_lLastUpdate); - } } } Modified: trunk/plugins/VeraControl/VeraCommunication.cs =================================================================== --- trunk/plugins/VeraControl/VeraCommunication.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/VeraCommunication.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -172,19 +172,20 @@ // Config data private string m_sVeraIPAddress; private string m_sVeraTCPIPPort; - private int m_iMaxRefreshDelay; + private int m_iMaxRefreshDelay; // Maximun delay between 2 status updates in seconds + private int m_iMinRefreshDelay = 1000; // Minimun delay between 2 status updates in miliseconds - // Actual device information private VeraStatus m_status = new VeraStatus(); // Communication status/control private long m_lLastUpdate = 0; - private bool m_bUpdatePending = false; private bool m_bScreenUpdateRequired = false; // Only true when a new update was received AND at least one device(staus) or scene was changed private bool m_bLastUpdateFailed = false; private string m_strLastUpdateError = ""; - private WebClient m_webClient = new WebClient(); + private WebClient m_webUpdateClient = new WebClient(); + private WebClient m_webCommandClient = new WebClient(); + private Action<string> m_webCommandClientReportError = null; // Action control table public int[] actionTriggerTable = new int[(int)Actiontrigger.LAST_ACTIONTRIGGER]; @@ -226,71 +227,113 @@ m_iMaxRefreshDelay = int.Parse(xmlreader.GetValueAsString("veracontroller", "maxrefreshdelay", "60")); // Set DownloadStringCompleted handler - m_webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(OnAsyncCompletedEventArgs); + m_webUpdateClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(OnCompletedUpdateStatusRequest); + m_webCommandClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(OnCompletedCommandRequest); } } - public void updateCurrentStatus(long lNow) - { - /* when to update in case connection gets lost --> keep updating with webClient timeout 180 sec....*/ - /* TODO: watch-dog !!! last time > 4 * maxDelay force an update - to recover from hibernate */ - if (m_bUpdatePending /* && m_lLastUpdate < ((lNow / 10000000) - (4 * m_iMaxRefreshDelay)) */) - { - return; - } - - m_bUpdatePending = true; - string url = "?id=lu_sdata&loadtime=" + m_status.system.loadtime + "&dataversion=" + m_status.system.dataversion + "&minimumdelay=2000&timeout=" + m_iMaxRefreshDelay + "&output_format=xml"; - doVeraRequest(url, OnAsyncCompletedEventArgs); - m_lLastUpdate = helper.getSecondsSince1970(); - } - public bool isVeraAlive(string ip, string port) { string response = retrieveURL("http://" + ip + ":" + port + "/data_request?id=lu_alive&time="+DateTime.Now.Ticks); - return (response == "OK"); } - public string doVeraRequest(string param) + private string retrieveURL(string url) { - return retrieveURL("http://" + vera_Address + "/data_request" + param + "&time="+DateTime.Now.Ticks); + // No callback thus Synchronised call (wait for response) + try { + WebClient wc = new WebClient(); + wc.CancelAsync(); // Cancel any current pending Async calls... + return wc.DownloadString(url); + } catch( Exception ) + { + return "ERROR"; + } } - public void doVeraRequest(string param, Action<object, DownloadStringCompletedEventArgs> onCallBack) + public void doVeraCommandRequest(string param, Action<string> errorReporter) { - retrieveURLAsync("http://" + vera_Address + "/data_request" + param + "&time="+DateTime.Now.Ticks); - } - - private string retrieveURL(string url) - { - // No callback thus Synchronised call (wait for response) + if (m_webCommandClient.IsBusy) + { + // TODO: What to do ? cancel pending request or queue new request? + } + string url = "http://" + vera_Address + "/data_request" + param + "&time="+DateTime.Now.Ticks; + + // Callback thus ASynchronised call (do NOT wait for response) try { - m_webClient.CancelAsync(); // Cancel any current pending Async calls... - return m_webClient.DownloadString(url); + m_webCommandClientReportError = errorReporter; + m_webCommandClient.CancelAsync(); // Cancel any current pending Async calls... + m_webCommandClient.DownloadStringAsync(new Uri(url)); + } catch( Exception e ) { - m_bLastUpdateFailed = true; - m_strLastUpdateError = e.Message; - return "ERROR"; + m_webCommandClientReportError = null; + status.system.reportCommandError(e.Message); + m_bScreenUpdateRequired = true; } - } - private void retrieveURLAsync(string url) + public void OnCompletedCommandRequest(object sender, DownloadStringCompletedEventArgs e) { - // Callback thus ASynchronised call (do NOT wait for response) + if (e.Cancelled) { + // Communication cancel for some reason, no valid data to be expected + if (m_webCommandClientReportError != null) { + m_webCommandClientReportError("Request was canceled"); + } else { + status.system.reportCommandError("Request was canceled"); + } + m_bScreenUpdateRequired = true; + } else if (e.Error != null) { + // Handle error here + if (m_webCommandClientReportError != null) { + m_webCommandClientReportError(e.Error.Message); + } else { + status.system.reportCommandError(e.Error.Message); + } + m_bScreenUpdateRequired = true; + } else { + // Communication succes full -> no parse Vera response... + if (!e.Result.ToUpper().Contains("<OK>OK</OK>") && !e.Result.ToUpper().Contains("<JOBID>")) + { + if (m_webCommandClientReportError != null) { + m_webCommandClientReportError(e.Result); + } else { + status.system.reportCommandError(e.Result); + } + m_bScreenUpdateRequired = true; + } + } + m_webCommandClientReportError = null; + } + + + public void updateCurrentStatus() + { + /* Keep updating with webClient timeout 180 sec, even when last time did fail or connection was lost....*/ + if (!m_webUpdateClient.IsBusy) + { + string url = "http://" + vera_Address + "/data_request" + + "?id=lu_sdata&loadtime=" + m_status.system.loadtime + + "&dataversion=" + m_status.system.dataversion + + "&minimumdelay=" + m_iMinRefreshDelay + + "&timeout=" + m_iMaxRefreshDelay + + "&output_format=xml" + + "&time="+DateTime.Now.Ticks; + + // Callback thus ASynchronised call (do NOT wait for response) try { - m_webClient.CancelAsync(); // Cancel any current pending Async calls... - m_webClient.DownloadStringAsync(new Uri(url)); + m_webUpdateClient.CancelAsync(); // Cancel any current pending Async calls... + m_webUpdateClient.DownloadStringAsync(new Uri(url)); } catch( Exception e ) { m_bLastUpdateFailed = true; m_strLastUpdateError = e.Message; } + m_lLastUpdate = helper.getSecondsSince1970(); + } } - - public void OnAsyncCompletedEventArgs(object sender, DownloadStringCompletedEventArgs e) + + public void OnCompletedUpdateStatusRequest(object sender, DownloadStringCompletedEventArgs e) { if (!e.Cancelled) { @@ -311,14 +354,18 @@ // update timer again (took some time to get the data) m_lLastUpdate = helper.getSecondsSince1970(); - m_bUpdatePending = false; } public void ParseUpdateInfo(string veraresponse) { var xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(veraresponse); - + try { + xmlDoc.LoadXml(veraresponse); + } catch (Exception) + { + // Parser failed so in correct data received (could be an interrupted data transfer) + return; + } // Parse header XmlNode rootnode = xmlDoc.SelectSingleNode("/root"); if (rootnode == null) @@ -342,7 +389,7 @@ m_status.system.update(rootnode); if (m_status.system.fullReload) { - // We have a full refresh -> Clear all lists (to get clear of removed devices) TODO: check/handle selected index when an item was deleted... + // We have a full refresh -> Clear all lists (to get clear of removed devices) m_status.clearAllLists(); } @@ -578,7 +625,7 @@ public bool updatePending { - get { return m_bUpdatePending; } + get { return m_webUpdateClient.IsBusy; } set { } } Modified: trunk/plugins/VeraControl/VeraControl.cs =================================================================== --- trunk/plugins/VeraControl/VeraControl.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/VeraControl.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -207,7 +207,7 @@ // Handle MP start-up trigger - do this is a different Thread to not block MP-start up new Thread( () => { - vera.updateCurrentStatus(DateTime.Now.Ticks); + vera.updateCurrentStatus(); // Run startup trigger after first update if (enableSceneTrigger) { @@ -481,9 +481,10 @@ if (!bLastUpdateFailed) { if (vera.status.system.dataversion == "0") - { // Give message on never connected... + { // Give message dialog on never connected... new Thread (() => { NoConnection(vera.lastUpdateError);}).Start(); } else { + // Give an error message on screen vera.status.system.reportConnectionError(vera.lastUpdateError); } } @@ -495,7 +496,7 @@ } // vera will only update when realy required - vera.updateCurrentStatus((long)timePassed); + vera.updateCurrentStatus(); refreshNow(); base.Render(timePassed); @@ -511,39 +512,51 @@ setSystemStatus(); } - // update device status - if (m_iSelectedRoom != Int16.MaxValue) + // if full reload has been found rebuild lists + if (vera.status.system.fullReload ) { + listRooms(m_iSelectedCategory, m_iSelectedRoom); + if (m_iSelectedRoom == Int16.MaxValue) { + listScenes(); + } else { + listDevices(m_iSelectedRoom); + } + } + else { - foreach (GUIListItem item in RightList.ListItems) + // update device status + if (m_iSelectedRoom != Int16.MaxValue) { - DeviceGeneric dev = vera.status.getDeviceById( item.ItemId ); - if (dev.newScreenUpdateWaitingAndClearFlag()) + foreach (GUIListItem item in RightList.ListItems) { - item.Label2 = dev.getStatusText(); - item.PinImage = helper.getStateImage(dev.commstate); - - //Adjust color of item when option is turned off - item.IsPlayed = !dev.isControllable; - - item.IconImage = "Vera\\"+dev.getIconName()+".png"; - item.IconImageBig = "Vera\\"+dev.getIconName()+".png"; - item.ThumbnailImage = "Vera\\"+dev.getIconName()+".png"; - - Utils.SetDefaultIcons(item); + DeviceGeneric dev = vera.status.getDeviceById( item.ItemId ); + if (dev.newScreenUpdateWaitingAndClearFlag()) + { + item.Label2 = dev.getStatusText(); + item.PinImage = helper.getStateImage(dev.commstate); + + //Adjust color of item when option is turned off + item.IsPlayed = !dev.isControllable; + + item.IconImage = "Vera\\"+dev.getIconName()+".png"; + item.IconImageBig = "Vera\\"+dev.getIconName()+".png"; + item.ThumbnailImage = "Vera\\"+dev.getIconName()+".png"; + + Utils.SetDefaultIcons(item); + } } } - } - else - { - foreach(GUIListItem item in RightList.ListItems) + else { - Scene scene = vera.status.getSceneById( item.ItemId ); - if (scene.newScreenUpdateWaitingAndClearFlag()) + foreach(GUIListItem item in RightList.ListItems) { - item.Label2 = (scene.room == 0 ? "" : vera.status.getRoomById(scene.room).name); - item.PinImage = helper.getStateImage(scene.commstate); - item.IsPlayed = scene.isActive(); - Utils.SetDefaultIcons(item); + Scene scene = vera.status.getSceneById( item.ItemId ); + if (scene.newScreenUpdateWaitingAndClearFlag()) + { + item.Label2 = (scene.room == 0 ? "" : vera.status.getRoomById(scene.room).name); + item.PinImage = helper.getStateImage(scene.commstate); + item.IsPlayed = scene.isActive(); + Utils.SetDefaultIcons(item); + } } } } @@ -571,8 +584,7 @@ base.OnPageLoad(); } - - + private void setSystemStatus() { if (vera.status.system.state != DevState.NONE) { @@ -587,6 +599,7 @@ comment.Label = vera.status.system.comment; } + private void listCategories() { int iCnt = 1; Modified: trunk/plugins/VeraControl/VeraControl.csproj =================================================================== --- trunk/plugins/VeraControl/VeraControl.csproj 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/VeraControl.csproj 2012-01-17 23:06:18 UTC (rev 4408) @@ -83,6 +83,7 @@ </Reference> </ItemGroup> <ItemGroup> + <Compile Include="BaseDevice.cs" /> <Compile Include="DevCategories.cs" /> <Compile Include="DeviceCam.cs" /> <Compile Include="DeviceDimmer.cs" /> Modified: trunk/plugins/VeraControl/VeraHelper.cs =================================================================== --- trunk/plugins/VeraControl/VeraHelper.cs 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/VeraHelper.cs 2012-01-17 23:06:18 UTC (rev 4408) @@ -13,7 +13,6 @@ namespace VeraControl.Properties { - public enum DevState { NONE = 0, @@ -21,7 +20,8 @@ SUCCESS, ERROR, - CONNECTION_ERROR // not a Vera state + CONNECTION_ERROR, // not a Vera state: update request failed + COMMAND_ERROR // not a Vera state: command request failed } /// <summary> @@ -79,6 +79,9 @@ { switch(state) { + case DevState.NONE: + return ""; + case DevState.PENDING: return "remote_blue.png"; @@ -87,14 +90,14 @@ case DevState.ERROR: return "tvguide_recordconflict_button.png"; - + + case DevState.COMMAND_ERROR: + return "tvguide_record_button.png"; + case DevState.CONNECTION_ERROR: + default: return "warning-icon.png"; - - default: - case DevState.NONE: - return ""; - + } } @@ -128,7 +131,7 @@ public long getSecondsSince1970() { - return (DateTime.Now.Ticks / 10000000); + return (DateTime.Now.Ticks / TimeSpan.TicksPerSecond); } } } Modified: trunk/plugins/VeraControl/skin/Default/VeraDialogDeviceControl.xml =================================================================== --- trunk/plugins/VeraControl/skin/Default/VeraDialogDeviceControl.xml 2012-01-17 23:05:16 UTC (rev 4407) +++ trunk/plugins/VeraControl/skin/Default/VeraDialogDeviceControl.xml 2012-01-17 23:06:18 UTC (rev 4408) @@ -222,7 +222,6 @@ <id>15</id> <description>Dimmable Light</description> <type>slider</type> - <id>15</id> <posX>330</posX> <posY>345</posY> <spintype>Int</spintype> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |