Now it works as it should when running it locally on the server. I am not that good with the remoting stuff. Had to rip off https://github.com/alexdresko/HSPI. Thanks a lot to alexdresko for "paving the way".
Announcement
Collapse
No announcement yet.
HSPI_MoskusSample - An easier plugin sample [VB.NET]
Collapse
X
-
Originally posted by Guahtdim View PostNow it works as it should when running it locally on the server. I am not that good with the remoting stuff. Had to rip off https://github.com/alexdresko/HSPI. Thanks a lot to alexdresko for "paving the way".Fred
HomeSeer Pro 3.0.0.548, HS3Touch, Zwave 3.0.1.252, Envisalink DSC 3.0.0.40, WeatherXML, Z-stick, HS phone, Way2Call
Comment
-
Need a little help with CsharpSample.
Please excuse the total "noob" question, but I'm tired of beating my head against this particular wall.
I've created a new class (CallMgrCls) which contains a static method called CallMgr. [I have to use
static methods because the Way2Call driver requires them.] What do I need to add to the new class
(or method) to be able to use methods in Utils? I created a simple test method that will compile and
run in a new thread started from InitIO. The first "generic" _utils.log executes, but when it reaches
the first _utils.log debug statement, it abends with a null reference exception on _settings.
Any help would be greatly appreciated!
Here's the code for the class:
<code>
using System;
using System.Configuration;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HSPI_CallMgr.Config;
using HSPI_CallMgr.HomeSeerClasses;
using HomeSeerAPI;
using Scheduler;
namespace HSPI_CallMgr
{
public class CallMgrCls
{
private Utils _utils;
private Settings _settings;
readonly static ConsoleColor cc = Console.ForegroundColor; // Console text color
private HsCollection _triggers = new HsCollection();
private IHSApplication _hs;
public Utils Utils
{
get => _utils;
set
{
_utils = value;
_hs = Utils.Hs;
}
}
public Settings Settings
{
get => _settings;
set => _settings = value;
}
// ============================================================ ==================
// ============================================================ ==================
public static void CallMgr()
{
Console.WriteLine("CallMgr starting");
Plugin pi = new Plugin();
Utils _utils = new Utils(pi.Settings);
_utils.Log("CallMgr starting - generic");
_utils.Log("CallMgr starting - debug", LogType.Debug);
ConsoleKeyInfo cki;
while (true) // Loop indefinitely
{
// check if user requesting program exit
Console.WriteLine("\nWaiting for call. Enter 'x' to exit pgm):");
cki = Console.ReadKey(false);
if (cki.KeyChar == 'x')
{
break;
}
}
}
Fred
HomeSeer Pro 3.0.0.548, HS3Touch, Zwave 3.0.1.252, Envisalink DSC 3.0.0.40, WeatherXML, Z-stick, HS phone, Way2Call
Comment
-
If the log - CallMgr starting - generic is executed I really don't know
It is hard to see where the error is, but a null reference exception will normally occure due to something not properly initialized. My guess is that your new utils class does not have the proper settings for HS. You need to add something like
_utils.Hs=_hs
within CallMgr() right after
Utils _utils = new Utils(pi.Settings);
But this is just speculation since I dont see how you start this thread from InitIO. Why do you start it as a new thread?
Comment
-
Originally posted by Guahtdim View PostIf the log - CallMgr starting - generic is executed I really don't know
It is hard to see where the error is, but a null reference exception will normally occure due to something not properly initialized. My guess is that your new utils class does not have the proper settings for HS. You need to add something like
_utils.Hs=_hs
within CallMgr() right after
Utils _utils = new Utils(pi.Settings);
When it throws the exception, it VS2017 highlights the red line below in "public void log" in Utils:
Code:public void Log(string message, LogType logLevel = LogType.Normal) { switch (logLevel) { case LogType.Debug: [COLOR=#FF0000] if (_settings.DebugLog)[/COLOR] { Hs.WriteLog(Utils.PluginName + " Debug", message); }
Error CS0176 Member 'Utils.Hs' cannot be accessed with an instance reference; qualify it with a type name instead
But this is just speculation since I dont see how you start this thread from InitIO. Why do you start it as a new thread?The SDK discussions say to start a new thread out of INITIO so you can return from INITIO quickly, so I just blindly did that.
Here's how I'm starting the thread:
CallMgrCls CallMgrCls = new CallMgrCls();
Thread thread = new Thread(CallMgrCls.CallMgr);
thread.Start();
FredFred
HomeSeer Pro 3.0.0.548, HS3Touch, Zwave 3.0.1.252, Envisalink DSC 3.0.0.40, WeatherXML, Z-stick, HS phone, Way2Call
Comment
-
Originally posted by Guahtdim View PostJust use the csharpsample and start changing the Plugin.cs to fit your needs.
Fred
HomeSeer Pro 3.0.0.548, HS3Touch, Zwave 3.0.1.252, Envisalink DSC 3.0.0.40, WeatherXML, Z-stick, HS phone, Way2Call
Comment
-
I think you have chosen a difficult way to learn both C# and Homeseer plugin programming.
You should read through the comments in Plugin. cs and get a feel for how the "flow" goes in a plugin.
What do you want to accomplish ?
As it is now your class is just waiting for keyboard input in the console. That will normally not happen that way in a Homeseer plugin.
Comment
-
Originally posted by Guahtdim View PostI think you have chosen a difficult way to learn both C# and Homeseer plugin programming.
You should read through the comments in Plugin. cs and get a feel for how the "flow" goes in a plugin.
What do you want to accomplish ?
As it is now your class is just waiting for keyboard input in the console. That will normally not happen that way in a Homeseer plugin.
The base code is pretty much the CsharpSample with just the timer stuff removed, and some Way2Call error-checking and the thread-start added ti InitIO. IniIO code below.
Thanks for your help.
Here's the code for InitIO.
Code:public string InitIO(string port) { Console.WriteLine("Starting initializiation."); //Loading settings before we do anything else _settings.Load(); //Registering two pages _utils.RegisterWebPage(ConfigPageName, "Config", "Configuration"); // _utils.RegisterWebPage(StatusPageName, "", "Demo test"); //Adding a trigger //_triggers.Add(null, "Random value is lower than"); //Adding a second trigger with subtriggers //... so first let us create the subtriggers var subtriggers = new HsTrigger(); subtriggers.Add(null, "On the first ring Of the phone"); subtriggers.Add(null, "On Each ring Of the phone"); subtriggers.Add(null, "When caller i.d. information Is available"); subtriggers.Add(null, "When the phone Is answered by a person"); subtriggers.Add(null, "When the phone Is answered by Homeseer"); subtriggers.Add(null, "When a voicemail message has been left"); subtriggers.Add(null, "When a voicemail message has been listened To"); subtriggers.Add(null, "When the phone handset Is lifted"); subtriggers.Add(null, "When the phone handset Is hung up"); subtriggers.Add(null, "When a phone call ends"); subtriggers.Add(null, "When digits entered on a telephone match"); subtriggers.Add(null, "When the dialed telephone number Is"); _utils.Log("Sub-triggers added", LogType.Debug); //... and then the trigger with the subtriggers _triggers.Add(subtriggers, "A telephone Event occurs"); _utils.Log("Main trigger added", LogType.Debug); //Adding an action _actions.Add(null, "Send a custom command somewhere"); _utils.Log("Action added", LogType.Debug); //Checks if plugin devices are present, and create them if not. //CheckAndCreateDevices(); _utils.Log("Devices checked/added", LogType.Debug); // If modem type is 1 (Way2Call Hi-phone), check if Hi-phone is connected if (_settings.ModemType == "1") { CWay2callDriver w2cDrv = new CWay2callDriver(); // The Way2Call Driver object int iErr = 0; CWay2callDriver.Errors w2cErr = CWay2callDriver.Errors.SUCCESS; Console.Clear(); Console.WriteLine("Initializing Way2call driver ...\n"); _utils.Log("Initializing Way2call HiPhone driver", LogType.Debug); // Note the CWay2callDriver.Errors usage w2cErr = (CWay2callDriver.Errors)w2cDrv.InitializeDriver(0);//must be called first if (CWay2callDriver.Errors.SUCCESS != w2cErr) { Console.WriteLine("Error opening the driver ...: " + w2cErr.ToString()); _utils.Log("Error opening the HiPhone driver", LogType.Debug); iErr = w2cDrv.ShutdownDriver(0); return "Error opening Hi-phone driver"; } // no device(s)... if (w2cDrv.NumDevices == 0) { Console.WriteLine("There are no Hi-Phone devices connected to this PC."); _utils.Log("There are no Hi-Phone devices connected to this PC.", LogType.Debug); iErr = w2cDrv.ShutdownDriver(0); return "No hi-phone attached"; } } // FOR TESTING - list all triggers for this plugin TriggerCheck(); Console.WriteLine("Initializing done! Ready..."); _utils.Log("Initializing done!", LogType.Debug); // Start the thread that does the actual work //CallMgrCls CallMgrCls = new CallMgrCls(); //Thread thread = new Thread(CallMgrCls.CallMgr); //thread.Start(); // Start the thread that does the actual work Plugin pi = new Plugin(); Thread thread = new Thread(pi.CallMgrStart); thread.Start(); _utils.Log("CallMgr thread submitted", LogType.Debug); return ""; } ​​​​​​​
Here's the code for the "real" CallMgr methods. In this early version, only the "On caller ID" handler actually tries to trigger a HS trigger.
Code:using System; using System.Configuration; using System.Collections.Specialized; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Web; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using HSPI_CallMgr.Config; using HSPI_CallMgr.HomeSeerClasses; using HomeSeerAPI; using Scheduler; // using Way2call; using Way2call.Driver; namespace HSPI_CallMgr { public class CallMgrCls { //private Utils _utils; //private Settings _settings; // Global vars const string sLogo = ".NET Call Manager console application\n"; static CWay2callDriver w2cDrv = new CWay2callDriver(); // The Way2Call Driver object readonly static ConsoleColor cc = Console.ForegroundColor; // Console text color static int MyCallConnected = 0; // Call connected flag static int MyCallHangup = 0; // Hangup current call flag private HsCollection _triggers = new HsCollection(); private IHSApplication _hs; //public Utils Utils //{ // get => _utils; // set // { // _utils = value; // _hs = Utils.Hs; // } //} //public Settings Settings // { // get => _settings; // set => _settings = value; // } // ============================================================================== ///Enum to determine which type of trigger we have ///</summary> private enum TriggerTypes { WithoutSubtriggers = 1, WithSubtriggers = 2 } ///Enum to get the subtrigger, if the current trigger type = TriggerTypes.WithSubTriggers (2) for the current Event. ///</summary> private enum SubTriggerTypes { FirstRing = 1, EveryRing = 2, CIDavail = 3, AnswerPerson = 4, AnswerHS = 5, VoiceMailLeft = 6, VoiceMailListened = 7, HandsetLifted = 8, HandsetHungUp = 9, PhoneCallEnds = 10, DigitsMatch = 11, DialedNumberIs = 12 } // ============================================================================== //public static void CallMgr() public void CallMgr() { Console.WriteLine("CallMgr starting"); Plugin pi = new Plugin(); Utils _utils = new Utils(pi.Settings); _utils.Log("CallMgr starting", LogType.Debug); int iErr = 0; ConsoleKeyInfo cki; // int ModemType = 1; // Modem type 1 is Hi-phone // This will allow for later addition of other types of modems // if modem is a Way2Call Hi-phone, process using these methods // if (ModemType == 1) //{ // Note the CWay2callDriver.Errors usage CWay2callDriver.Errors w2cErr = CWay2callDriver.Errors.SUCCESS; Console.WriteLine(sLogo); // add the event handlers. Note that these are REQUIRED to be static. // Generic handler - just shows events received CWay2callDriver.OnNativeDeviceEvent += new CWay2callDriver.DelegateNativeDeviceEvent(CWay2callDriver_OnNativeDeviceEvent); // When Hi-phone detects call connected CWay2callDriver.OnCallConnected += new CWay2callDriver.DelegateNoParams(CWay2callDriver_OnCallConnected); // Silence detected on line CWay2callDriver.OnSilentDetected += new CWay2callDriver.DelegateNoParams(CWay2callDriver_OnSilentDetected); // Line current drop detected on line CWay2callDriver.OnLineCurrentDrop += new CWay2callDriver.DelegateNoParams(CWay2callDriver_OnLineCurrentDrop); // Caller id info has been received CWay2callDriver.OnCallerID += new CWay2callDriver.DelegateOnCallerID(CWay2callDriver_OnCallerID); // Async playback completed - raised when an audio file finishes playing CWay2callDriver.OnAsyncPlaybackDone += new CWay2callDriver.DelegateNoParams(CWay2callDriver_OnAsyncPlaybackDone); Console.WriteLine("Driver version: " + w2cDrv.Version.ToString() + "\n"); //assume device #0 exists w2cErr = (CWay2callDriver.Errors)w2cDrv.Device.Open(0);//open the device if (CWay2callDriver.Errors.SUCCESS != w2cErr) { Console.WriteLine("Error opening the device ...: " + w2cErr.ToString()); iErr = w2cDrv.ShutdownDriver(0);//must be last called return; } // Setup the Hiphone unit from ini file Setup_hip(); //} Console.WriteLine("Checking for triggers"); //Plugin pi = new Plugin(); //Utils _utils = new Utils(pi.Settings); pi.TriggerCheck(); while (true) // Loop indefinitely { // check if user requesting program exit Console.WriteLine("\nWaiting for call. Enter 'x' to exit pgm):"); cki = Console.ReadKey(false); if (cki.KeyChar == 'x') { break; } } iErr = w2cDrv.Device.Close(0); //close the device iErr = w2cDrv.ShutdownDriver(0); //shut down the driver - must be last called } // ------------------------------------------------------------------------- // generic / native device event handler static void CWay2callDriver_OnNativeDeviceEvent(ushort DeviceID, uint Event, uint EventData, uint EventDataEx, byte[] pEventBuffer) { //print event's description Console.ForegroundColor = ConsoleColor.DarkCyan; Console.WriteLine("Device Event: " + w2cDrv.Device[DeviceID].EventDescription(Event, EventData)); Console.ForegroundColor = cc; } // ------------------------------------------------------------------------- // line current dropped (remote hung up) so we set flag and hang up call static void CWay2callDriver_OnLineCurrentDrop(ushort DeviceID) { Console.WriteLine("Caller hung up\n"); w2cDrv.Device.HangUp(false); // MyCallHangup = 0; Hangup(); } // ------------------------------------------------------------------------- // call connected event handler (for outbound calls) static void CWay2callDriver_OnCallConnected(ushort DeviceID) { if (0 != MyCallConnected) return;//event may be fired mutiple times MyCallConnected = 1;//mark call connected; // unmute local device w2cDrv.Device.AudioControl.LocalDeviceToLine = CWay2callDriver.CDevice.CAudioControl.SIGNAL_SWITCH.UnMute; // connect local device to both line and PC audio w2cDrv.Device.SwitchingMode = CWay2callDriver.CDevice.SwitchingModes.Line_PcAudio_Phone; Console.WriteLine("Call connected\n"); return; } // ------------------------------------------------------------------------- // Caller ID info received handler static void CWay2callDriver_OnCallerID(ushort DeviceID, string sCid) { Console.ForegroundColor = ConsoleColor.DarkCyan; Console.WriteLine("CID detected\n"); Console.WriteLine("CID string: " + sCid + "\n"); Console.ForegroundColor = cc; Console.WriteLine("Calling TriggerCheckFire "); //Getting all triggers for this plugin (this only returns triggers where it is the FIRST option in an event, not when it's used as a condition) //HomeSeerAPI.IPlugInAPI.strTrigActInfo[] triggers = _utils.Callback.GetTriggers(Utils.PluginName); //Console.WriteLine("\tTriggers found: " + Utils.triggers.Count()); Plugin pi = new Plugin(); pi.TriggerCheckFire(); return; } // ------------------------------------------------------------------------- // silence-detection event handler static void CWay2callDriver_OnSilentDetected(ushort DeviceID) { Console.ForegroundColor = ConsoleColor.DarkCyan; Console.WriteLine("Silence detected\n"); Console.ForegroundColor = cc; } // ------------------------------------------------------------------------- // playback done event handler static void CWay2callDriver_OnAsyncPlaybackDone(ushort DeviceID) { Console.WriteLine("\n Announcement fileplay is complete."); if (0 == MyCallHangup) return; // call should now be hung up Hangup(); } // ------------------------------------------------------------------------- // Setup Hi-Phone static void Setup_hip() { Console.WriteLine("Setting up the Hi-Phone...\n"); } // ------------------------------------------------------------------------- // Hangup Hi-Phone static void Hangup() { Console.WriteLine("Hanging up the Hi-Phone...\n"); w2cDrv.Device.HangUp(false); MyCallHangup = 0; } } }
Fred
HomeSeer Pro 3.0.0.548, HS3Touch, Zwave 3.0.1.252, Envisalink DSC 3.0.0.40, WeatherXML, Z-stick, HS phone, Way2Call
Comment
-
I would probably do this first:
Create a standalone Console application that does what you want without involving Homeseer. As it is I think you need to focus on the main problem - Connecting to Way2Call and see that you can register the different events that you want to trigger in HomeSeer. Just use the most primitive method we have: Console.WriteLine("Something happend!")
When you have a working console application up and running, catching all the events you want to trigger then you try to make it into a plugin.
I often start that way since I get a much shorter develop/see response cycle. If you involve HomeSeer in the early stages you only add more complication.
Test-driven development would also be a good idea since you might have to split out the Way2CallDriver just for easier testing of your application.
Comment
-
Originally posted by Guahtdim View PostI would probably do this first:
Create a standalone Console application that does what you want without involving Homeseer.
Thanks again for your help!
Fred
HomeSeer Pro 3.0.0.548, HS3Touch, Zwave 3.0.1.252, Envisalink DSC 3.0.0.40, WeatherXML, Z-stick, HS phone, Way2Call
Comment
-
OK, I decided to take a step back. Here's what I did:
1. Created a fresh copy of CsharpSample - Master
2. Built it and verified that it runs correctly.
3. Added a new method to Plugin.cs called TriggerCheck. [code is below]. It just lists triggers for this plugin to the console.
4. Added a call to TriggerCheck in InitIO. [code below]
5. Rebuilt and verified that the new method ran properly.
6. Added my simplified CallMgrCls to the project. [code below]
7. Added a thread start to InitIO to start the CallMgr method.
8. Rebuilt
9. Ran new build in debug. TriggerCheck in InitIO runs properly. Thread for CallMgr starts properly and shows "CallMgr starting" on the console.
The call to TriggerCheck abends with a "null reference" exception for _utils on the line :
HomeSeerAPI.IPlugInAPI.strTrigActInfo[] triggers = _utils.Callback.GetTriggers(Utils.PluginName);
I tried adding the _utils.hs = .hs that you suggested, but it gives a compiler error of:
Error CS0176 Member 'Utils.Hs' cannot be accessed with an instance reference; qualify it with a type name instead
If I can just get by this issue of being able to access the trigger-related stuff in Utils, I'd be ready to rock and roll.
I know it's asking a lot, but if you could just recreate what I've done here, you'll be able to see exactly what's happening.
Thanks!
Code for TriggerCheck
Code:#region "Test routines" // ==================================================================== // Check triggers and list them to console // ==================================================================== public void TriggerCheck() { Console.WriteLine("TriggerCheck has been called"); Console.WriteLine("Looking for triggers for plugin: " + Utils.PluginName); //Getting all triggers for this plugin (this only returns triggers where it is the FIRST option in an event, not when it's used as a condition) HomeSeerAPI.IPlugInAPI.strTrigActInfo[] triggers = _utils.Callback.GetTriggers(Utils.PluginName); Console.WriteLine("\tTriggers found: " + triggers.Count()); foreach (var trigger in triggers) { Console.WriteLine("Event found with ref: " + trigger.evRef); } } #endregion
Code:public string InitIO(string port) { Console.WriteLine("Starting initializiation."); //Loading settings before we do anything else _settings.Load(); //Registering two pages _utils.RegisterWebPage(ConfigPageName, "Config", "Configuration"); _utils.RegisterWebPage(StatusPageName, "", "Demo test"); //Adding a trigger _triggers.Add(null, "Random value is lower than"); //Adding a second trigger with subtriggers //... so first let us create the subtriggers var subtriggers = new HsTrigger(); subtriggers.Add(null, "Random value is lower than"); subtriggers.Add(null, "Random value is equal to"); subtriggers.Add(null, "Random value is higher than"); //... and then the trigger with the subtriggers _triggers.Add(subtriggers, "Random value is..."); //Adding an action _actions.Add(null, "Send a custom command somewhere"); //Checks if plugin devices are present, and create them if not. CheckAndCreateDevices(); //'Starting the update timer; a timer for fetching updates from the web (for example). However, in this sample, the UpdateTimerTrigger just generates a random value. (Should ideally be placed in its own thread, but I use a Timer here for simplicity). _updateTimer = new System.Threading.Timer(new TimerCallback(UpdateRandomValue), null, Timeout.Infinite, _settings.TimerInterval); RestartTimer(); // FOR TESTING - list all triggers for this plugin TriggerCheck(); // Start the thread that does the actual work CallMgrCls CallMgrCls = new CallMgrCls(); Thread thread = new Thread(CallMgrCls.CallMgr); thread.Start(); Console.WriteLine("Initializing done! Ready..."); return ""; }
Code:using System; using System.Configuration; using System.Collections.Specialized; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Web; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using HSPI_CsharpSample.Config; using HSPI_CsharpSample.HomeSeerClasses; using HomeSeerAPI; using Scheduler; namespace HSPI_CsharpSample { public class CallMgrCls { //private Utils _utils; //private Settings _settings; //private HsCollection _triggers = new HsCollection(); private IHSApplication _hs; // ============================================================================== // ============================================================================== public void CallMgr() { Console.WriteLine("CallMgr starting"); Plugin pi = new Plugin(); Utils _utils = new Utils(pi.Settings); //_utils.Hs = _hs; pi.TriggerCheck(); ConsoleKeyInfo cki; while (true) // Loop indefinitely { // check if user requesting program exit Console.WriteLine("\nWaiting for call. Enter 'x' to exit pgm):"); cki = Console.ReadKey(false); if (cki.KeyChar == 'x') { break; } } } } }
Fred
HomeSeer Pro 3.0.0.548, HS3Touch, Zwave 3.0.1.252, Envisalink DSC 3.0.0.40, WeatherXML, Z-stick, HS phone, Way2Call
Comment
-
Keep rewriting this post over and over again.
1. Do not create a new Plugin class inside CallMgrCls since this new class has no idea about all the stuff set up in the first Plugin created in Hspi.cs. You are better off asigning the existing plugin to your new class on New or as a property.
(this code is not good code, but it might get you started)
// Start the thread that does the actual work
CallMgrCls callMgrCls = new CallMgrCls();
callMgrCls.Plugin=this;
Thread thread = new Thread(CallMgrCls.CallMgr);
thread.Start();
..
..
in CallMgrCls
public class CallMgrCls {
private Plugin _plugin;
public Plugin Plugin {
set { _plugin=value; }
}
..
..
(remove the following 3 lines)
Plugin pi = new Plugin();
Utils _utils = new Utils(pi.Settings);
//_utils.Hs = _hs;
(replace pi.TriggerCheck(); with the following line)
_plugin.TriggerCheck();
This might work, but it is an ugly beast.
Comment
-
Originally posted by Guahtdim View PostKeep rewriting this post over and over again.
1. Do not create a new Plugin class inside CallMgrCls since this new class has no idea about all the stuff set up in the first Plugin created in Hspi.cs. You are better off asigning the existing plugin to your new class on New or as a property.
(this code is not good code, but it might get you started)
// Start the thread that does the actual work
CallMgrCls callMgrCls = new CallMgrCls();
callMgrCls.Plugin=this;
Thread thread = new Thread(CallMgrCls.CallMgr);
thread.Start();
..
..
in CallMgrCls
public class CallMgrCls {
private Plugin _plugin;
public Plugin Plugin {
set { _plugin=value; }
}
..
..
(remove the following 3 lines)
Plugin pi = new Plugin();
Utils _utils = new Utils(pi.Settings);
//_utils.Hs = _hs;
(replace pi.TriggerCheck(); with the following line)
_plugin.TriggerCheck();
This might work, but it is an ugly beast.
Using your suggested changes, because CallMgr is a static method, VS2017 still gives the CS0120 error saying that an object reference is required. I've done a lot of reading this morning (again) of the Microsoft C# documentation, as well as lots of posts on StackOverflow regarding similar issues. I know from experimenting that the issue is strictly related to trying to call a non-static method from within a static method - TriggerCheck in this case, but it applies to any of the methods in the sample.
Just to eliminate the extra class (CallMgrCls) as a possibility, I created another version where the simplified test CallMgr method is just included in the Plugin class. That works fine as long as CallMgr is not static. TriggerCheck runs fine from within CallMgr, and even _utils.Log works fine. But as soon as I change CallMgr to static, then the
CS0120 An object reference is required for the non-static field, method, or property 'Plugin.TriggerCheck()' error returns.
My conclusion is that there is something about the way CsharpSample is structured that just makes it impossible to use a static method with it .Fred
HomeSeer Pro 3.0.0.548, HS3Touch, Zwave 3.0.1.252, Envisalink DSC 3.0.0.40, WeatherXML, Z-stick, HS phone, Way2Call
Comment
Comment