public OnOffDigitalSensorMgr(int pTimeZoneOffset, int pDstOffset, string pDstStart, string pDstEnd, string pDestinationTable = "undef", string pSensorLabel = "undef", bool pInitialInputState = true, bool pInvertInputPolarity = false, string pSensorLocation = "undef", string pMeasuredQuantity = "undef", string pChannel = "000")
        {
            dstOffset = pDstOffset;
            dstStart  = pDstStart;
            dstEnd    = pDstEnd;
            input     = pInitialInputState;
            oldState  = pInitialInputState ? InputSensorState.High : InputSensorState.Low;

            timeZoneOffset   = pTimeZoneOffset;
            sensorLabel      = pSensorLabel;
            sensorLocation   = pSensorLocation;
            measuredQuantity = pMeasuredQuantity;
            destinationTable = pDestinationTable;
            channel          = pChannel;
            DateTime timeZoneCorrectedDateTime = DateTime.Now.AddMinutes(timeZoneOffset);

            dateTimeOfLastSend = timeZoneCorrectedDateTime.AddMinutes(GetDlstOffset.Get(timeZoneCorrectedDateTime, pDstStart, pDstEnd, pDstOffset));
            invertPolarity     = pInvertInputPolarity;
            _stopped           = true;
            ReadSensorThread   = new Thread(new ThreadStart(runReadSensorThread));
            ReadSensorThread.Start();
        }
        private void runReadSensorThread()
        {
            DateTime timeZoneCorrectedDateTime;
            DateTime actDateTime;

            while (true)
            {
                if (!_stopped)
                {
                    if (input ^ invertPolarity == false)
                    {
                        Thread.Sleep(20);         // debouncing
                        if (input ^ invertPolarity == false)
                        {
                            if (oldState == InputSensorState.High)
                            {
                                timeZoneCorrectedDateTime = DateTime.Now.AddMinutes(timeZoneOffset);
                                actDateTime = timeZoneCorrectedDateTime.AddMinutes(GetDlstOffset.Get(timeZoneCorrectedDateTime, dstStart, dstEnd, dstOffset));
                                actState    = InputSensorState.Low;
                                TimeSpan timeFromLastSend = actDateTime - dateTimeOfLastSend;
                                OnDigitalOnOffSensorSend(this, new OnOffSensorEventArgs(actState, oldState, actDateTime, timeFromLastSend, onTimeDay, sensorLabel, sensorLocation, measuredQuantity, destinationTable, channel, false));
                                dateTimeOfLastSend = actDateTime;
                                oldState           = InputSensorState.Low;
                            }
                        }
                    }
                    else
                    {
                        Thread.Sleep(20);                   // (debouncing)
                        if (input ^ invertPolarity == true) // input still high
                        {
                            if (oldState == InputSensorState.Low)
                            {
                                timeZoneCorrectedDateTime = DateTime.Now.AddMinutes(timeZoneOffset);
                                actDateTime = timeZoneCorrectedDateTime.AddMinutes(GetDlstOffset.Get(timeZoneCorrectedDateTime, dstStart, dstEnd, dstOffset));
                                actState    = InputSensorState.High;
                                TimeSpan timeFromLastSend = actDateTime - dateTimeOfLastSend;
                                onTimeDay += timeFromLastSend;
                                OnDigitalOnOffSensorSend(this, new OnOffSensorEventArgs(actState, oldState, actDateTime, timeFromLastSend, onTimeDay, sensorLabel, sensorLocation, measuredQuantity, destinationTable, channel, false));
                                dateTimeOfLastSend = actDateTime;
                                oldState           = InputSensorState.High;
                            }
                        }
                    }

                    // Send an input high event (means: is off) in the last 30 seconds of each day and wait on the next day
                    timeZoneCorrectedDateTime = DateTime.Now.AddMinutes(timeZoneOffset);
                    actDateTime = timeZoneCorrectedDateTime.AddMinutes(GetDlstOffset.Get(timeZoneCorrectedDateTime, dstStart, dstEnd, dstOffset));
                    if (actDateTime.Hour == 23 && actDateTime.Minute == 59 && actDateTime.Second > 30)
                    {
                        actState = InputSensorState.High;
                        TimeSpan timeFromLastSend = actDateTime - dateTimeOfLastSend;
                        onTimeDay += timeFromLastSend;
                        OnDigitalOnOffSensorSend(this, new OnOffSensorEventArgs(actState, oldState, actDateTime, timeFromLastSend, onTimeDay, sensorLabel, sensorLocation, measuredQuantity, destinationTable, channel, true));
                        oldState = InputSensorState.High;

                        // wait on the next day
                        while (actDateTime.Day == DateTime.Now.AddMinutes(timeZoneOffset).AddMinutes(GetDlstOffset.Get(DateTime.Now.AddMinutes(timeZoneOffset), dstStart, dstEnd, dstOffset)).Day)
                        {
                            Thread.Sleep(100);
                        }

                        onTimeDay = new TimeSpan(0, 0, 0);
                    }
                    Thread.Sleep(20);   // Read Sensor every 20 ms
                }
                else
                {
                    Thread.Sleep(200);   // When stopped, Read Sensor every 200 ms
                }
            }
        }