소스 검색

Begun addition of additional types of transceiver modules

Added support of PL1167_LT8900 module.
Missing settings in webapp.
WoodsterDK 8 년 전
부모
커밋
f864479249

+ 172 - 153
data/web/index.html

@@ -16,7 +16,7 @@
   <!--[if lt IE 9]>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
   <![endif]-->
-  
+
   <style>
     .header-row { border-bottom: 1px solid #ccc; }
     label { display: block; }
@@ -31,8 +31,8 @@
     .error-info:before { content: '('; }
     .error-info:after { content: ')'; }
     .header-btn { margin: 20px; }
-    .btn-secondary { 
-      background-color: #fff; 
+    .btn-secondary {
+      background-color: #fff;
       border: 1px solid #ccc;
     }
     .inline { display: inline-block; }
@@ -46,41 +46,41 @@
       width: calc(100% - 3em);
       display: inline-block;
       cursor: pointer;
-      background: linear-gradient(to right, 
-        rgb(255, 0, 0) 0%, 
-        rgb(255, 255, 0) 16.6667%, 
-        rgb(0, 255, 0) 33.3333%, 
-        rgb(0, 255, 255) 50%, 
-        rgb(0, 0, 255) 66.6667%, 
-        rgb(255, 0, 255) 83.3333%, 
+      background: linear-gradient(to right,
+        rgb(255, 0, 0) 0%,
+        rgb(255, 255, 0) 16.6667%,
+        rgb(0, 255, 0) 33.3333%,
+        rgb(0, 255, 255) 50%,
+        rgb(0, 0, 255) 66.6667%,
+        rgb(255, 0, 255) 83.3333%,
         rgb(255, 0, 0) 100%
       );
     }
-    .hue-value-display { 
+    .hue-value-display {
       border: 1px solid #000;
       margin-left: 0.5em;
       width: 2em;
       height: 2em;
       display: inline-block;
     }
-    .plus-minus-group { 
+    .plus-minus-group {
       overflow: auto;
       width: 100%;
       clear: both;
       display: block;
     }
-    .plus-minus-group button:first-of-type { 
+    .plus-minus-group button:first-of-type {
       border-bottom-right-radius: 0;
       border-top-right-radius: 0;
       float: left;
       display: block;
     }
-    .plus-minus-group button:last-of-type { 
+    .plus-minus-group button:last-of-type {
       border-bottom-left-radius: 0;
       border-top-left-radius: 0;
       display: block;
     }
-    .plus-minus-group .title { 
+    .plus-minus-group .title {
       border-width: 1px 0;
       border-color: #ccc;
       border-style: solid;
@@ -100,12 +100,12 @@
       animation: spin 1s infinite linear;
       -webkit-animation: spin2 1s infinite linear;
     }
-    
+
     @keyframes spin {
       from { transform: scale(1) rotate(0deg); }
       to { transform: scale(1) rotate(360deg); }
     }
-    
+
     @-webkit-keyframes spin2 {
       from { -webkit-transform: rotate(0deg); }
       to { -webkit-transform: rotate(360deg); }
@@ -120,14 +120,15 @@
   <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.0/bootstrap-slider.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.4/js/standalone/selectize.min.js"></script>
-  
+
   <script lang="text/javascript">
     var FORM_SETTINGS = [
-      "admin_username", "admin_password", "ce_pin", "csn_pin", "packet_repeats",
+      "admin_username", "admin_password", "ce_pin", "csn_pin", "reset_pin","packet_repeats",
       "http_repeat_factor", "auto_restart_period"
     ];
-    
+
     var FORM_SETTINGS_HELP = {
+      csn_pin_RxReady : "'csn' for 'nRF24' interface, and RxReady for 'PL1167_LT8900' interface",
       packet_repeats : "The number of times to repeat RF packets sent to bulbs",
       http_repeat_factor : "Multiplicative factor on packet_repeats for " +
         "requests initiated by the HTTP API. UDP API typically receives " +
@@ -135,37 +136,37 @@
       auto_restart_period : "Automatically restart the device every number of " +
         "minutes specified. Use 0 for disabled."
     }
-    
+
     var UDP_PROTOCOL_VERSIONS = [ 5, 6 ];
     var DEFAULT_UDP_PROTOCL_VERSION = 5;
-    
+
     var selectize;
-    
+
     var toHex = function(v) {
       return "0x" + (v).toString(16).toUpperCase();
     }
-  
+
     var activeUrl = function() {
       var deviceId = $('#deviceId option:selected').val()
         , groupId = $('#groupId .active input').data('value')
         , mode = getCurrentMode();
-        
+
       if (deviceId == "") {
         alert("Please enter a device ID.");
         throw "Must enter device ID";
       }
-      
+
       if (! $('#group-option').data('for').split(',').includes(mode)) {
         groupId = 0;
       }
-        
+
       return "/gateways/" + deviceId + "/" + mode + "/" + groupId;
     }
-    
+
     var getCurrentMode = function() {
       return $('input[name="mode"]:checked').data('value');
     };
-    
+
     var updateGroup = _.throttle(
       function(params) {
         $.ajax(
@@ -179,7 +180,7 @@
       },
       1000
     );
-    
+
     var sendCommand = _.throttle(
       function(params) {
         $.ajax(
@@ -193,18 +194,18 @@
       },
       1000
     )
-    
+
     var sniffRequest;
     var sniffing = false;
     var getTraffic = function() {
       var sniffType = $('#sniff-type input:checked').data('value');
-      
+
       sniffRequest = $.get('/gateway_traffic/' + sniffType, function(data) {
         $('#sniffed-traffic').html(data + $('#sniffed-traffic').html());
         getTraffic();
       });
     };
-    
+
     var gatewayServerRow = function(deviceId, port, version) {
       var elmt = '<tr>';
       elmt += '<td>';
@@ -215,17 +216,17 @@
       elmt += '</td>';
       elmt += '<td>';
       elmt += '<div class="btn-group" data-toggle="buttons">';
-      
+
       for (var i = 0; i < UDP_PROTOCOL_VERSIONS.length; i++) {
         var val = UDP_PROTOCOL_VERSIONS[i]
           , selected = (version == val || (val == DEFAULT_UDP_PROTOCL_VERSION && !UDP_PROTOCOL_VERSIONS.includes(version)));
-        
+
         elmt += '<label class="btn btn-secondary' + (selected ? ' active' : '') + '">';
-        elmt += '<input type="radio" name="versions[]" autocomplete="off" data-value="' + val + '" ' 
+        elmt += '<input type="radio" name="versions[]" autocomplete="off" data-value="' + val + '" '
           + (selected ? 'checked' : '') +'> ' + val;
         elmt += '</label>';
       }
-      
+
       elmt += '</div></td>';
       elmt += '<td>';
       elmt += '<button class="btn btn-danger remove-gateway-server">';
@@ -235,17 +236,17 @@
       elmt += '</tr>';
       return elmt;
     }
-    
+
     var loadSettings = function() {
       $.getJSON('/settings', function(val) {
         Object.keys(val).forEach(function(k) {
           var field = $('#settings input[name="' + k + '"]');
-          
+
           if (field.length > 0) {
             field.val(val[k]);
           }
         });
-        
+
         if (val.device_ids) {
           selectize.clearOptions();
           val.device_ids.forEach(function(v) {
@@ -253,7 +254,7 @@
           });
           selectize.refreshOptions();
         }
-        
+
         var gatewayForm = $('#gateway-server-configs').html('');
         if (val.gateway_configs) {
           val.gateway_configs.forEach(function(v) {
@@ -262,16 +263,16 @@
         }
       });
     };
-    
+
     var saveGatewayConfigs = function() {
       var form = $('#gateway-server-form')
         , errors = false;
-        
+
       $('input', form).removeClass('error');
-      
+
       var deviceIds = $('input[name="deviceIds[]"]', form).map(function(i, v) {
         var val = $(v).val();
-        
+
         if (isNaN(val)) {
           errors = true;
           $(v).addClass('error');
@@ -280,10 +281,10 @@
           return val;
         }
       });
-      
+
       var ports = $('input[name="ports[]"]', form).map(function(i, v) {
         var val = $(v).val();
-        
+
         if (isNaN(val)) {
           errors = true;
           $(v).addClass('error');
@@ -292,11 +293,11 @@
           return val;
         }
       });
-      
+
       var versions = $('.active input[name="versions[]"]', form).map(function(i, v) {
         return $(v).data('value');
       });
-        
+
       if (!errors) {
         var data = [];
         for (var i = 0; i < deviceIds.length; i++) {
@@ -312,7 +313,7 @@
         )
       }
     };
-    
+
     var deviceIdError = function(v) {
       if (!v) {
         $('#device-id-label').removeClass('error');
@@ -321,10 +322,10 @@
         $('#device-id-label .error-info').html(v);
       }
     };
-    
+
     var updateModeOptions = function() {
       var currentMode = getCurrentMode();
-      
+
       $('.mode-option').map(function() {
         if ($(this).data('for').split(',').includes(currentMode)) {
           $(this).show();
@@ -333,10 +334,10 @@
         }
       });
     };
-    
+
     var parseVersion = function(v) {
       var matches = v.match(/(\d+)\.(\d+)\.(\d+)(-(.*))?/);
-      
+
       return {
         major: matches[1],
         minor: matches[2],
@@ -345,28 +346,28 @@
         parts: [matches[1], matches[2], matches[3], matches[5]]
       };
     };
-    
+
     var isNewerVersion = function(a, b) {
       var va = parseVersion(a)
         , vb = parseVersion(b);
-        
+
       return va.parts > vb.parts;
     };
-    
+
     var handleCheckForUpdates = function() {
       var currentVersion = null
         , latestRelease = null;
-        
+
       var handleReceiveData = function() {
         if (currentVersion != null) {
           $('#current-version').html(currentVersion.version + " (" + currentVersion.variant + ")");
         }
-        
+
         if (latestRelease != null) {
           $('#latest-version .info-key').each(function() {
             var value = latestRelease[$(this).data('key')];
             var prop = $(this).data('prop');
-            
+
             if (prop) {
               $(this).prop(prop, value);
             } else {
@@ -374,11 +375,11 @@
             }
           });
         }
-        
+
         if (currentVersion != null && latestRelease != null) {
           $('#latest-version .status').html('');
           $('#latest-version-info').show();
-          
+
           var summary;
           if (isNewerVersion(latestRelease.tag_name, currentVersion.version)) {
             summary = "New version available!";
@@ -386,30 +387,30 @@
             summary = "You're on the most recent version.";
           }
           $('#version-summary').html(summary);
-          
+
           var releaseAsset = latestRelease.assets.filter(function(x) {
             return x.name.indexOf(currentVersion.variant) != -1;
           });
-          
+
           if (releaseAsset.length > 0) {
             console.log(releaseAsset[0].url);
             $('#firmware-link').prop('href', releaseAsset[0].browser_download_url);
           }
         }
-        
+
         console.log(latestRelease);
       }
-      
+
       var handleError = function(e, d) {
         console.log(e);
         console.log(d);
       }
-      
+
       $('#current-version,#latest-version .status').html('<i class="spinning glyphicon glyphicon-refresh"></i>');
       $('#version-summary').html('');
       $('#latest-version-info').hide();
       $('#updates-modal').modal();
-      
+
       $.ajax(
         '/about',
         {
@@ -420,7 +421,7 @@
           failure: handleError
         }
       );
-      
+
       $.ajax(
         '/latest_release',
         {
@@ -432,26 +433,26 @@
         }
       );
     };
-    
+
     $(function() {
       $('.radio-option').click(function() {
         $(this).prev().prop('checked', true);
       });
-      
+
       var hueDragging = false;
       var colorUpdated = function(e) {
         var x = e.pageX - $(this).offset().left
           , pct = x/(1.0*$(this).width())
           , hue = Math.round(360*pct)
           ;
-          
+
         $('.hue-value-display').css({
           backgroundColor: "hsl(" + hue + ",100%,50%)"
         });
-        
+
         updateGroup({hue: hue});
       };
-      
+
       $('.hue-picker-inner')
         .mousedown(function(e) {
           hueDragging = true;
@@ -468,26 +469,26 @@
             colorUpdated.call(this, e);
           }
         });
-        
+
       $('.slider').slider();
-      
+
       $('.raw-update').change(function() {
         var data = {}
           , val = $(this).attr('type') == 'checkbox' ? $(this).is(':checked') : $(this).val()
           ;
-          
+
         data[$(this).attr('name')] = val;
         updateGroup(data);
       });
-      
+
       $('.command-btn').click(function() {
         updateGroup({command: $(this).data('command')});
       });
-      
+
       $('.system-btn').click(function() {
         sendCommand({command: $(this).data('command')});
       });
-      
+
       $('#sniff').click(function() {
         if (sniffing) {
           sniffRequest.abort();
@@ -499,17 +500,17 @@
           $(this).html('Stop Sniffing');
         }
       });
-      
+
       $('#add-server-btn').click(function() {
         $('#gateway-server-configs').append(gatewayServerRow('', ''));
       });
-      
+
       $('#mode').change(updateModeOptions);
-      
+
       $('body').on('click', '.remove-gateway-server', function() {
         $(this).closest('tr').remove();
       });
-      
+
       selectize = $('#deviceId').selectize({
         create: true,
         sortField: 'text',
@@ -521,53 +522,71 @@
             deviceIdError("Must be an integer between 0x0000 and 0xFFFF");
             return false;
           }
-          
+
           var value = parseInt(v);
-          
+
           if (! (0 <= v && v <= 0xFFFF)) {
             deviceIdError("Must be an integer between 0x0000 and 0xFFFF");
             return false;
-          } 
-          
+          }
+
           deviceIdError(false);
-          
+
           return true;
         }
       });
       selectize = selectize[0].selectize;
-      
+
       var settings = "";
-      
+
       FORM_SETTINGS.forEach(function(k) {
         var elmt = '<div class="form-entry">';
         elmt += '<label for="' + k + '">' + k + '</label>';
-        
+
+        if (FORM_SETTINGS_HELP[k]) {
+          elmt += '<div class="field-help" data-help-text="' + FORM_SETTINGS_HELP[k] + '"></div>';
+        }
+
         if (FORM_SETTINGS_HELP[k]) {
           elmt += '<div class="field-help" data-help-text="' + FORM_SETTINGS_HELP[k] + '"></div>';
         }
-        
-        elmt += '<input type="text" class="form-control" name="' + k + '"/>';
-        elmt += '</div>';
-        
+
+        if(k === "radio_interface_type")
+        {
+          elmt += '<div class="btn-group" id="sniff-type" data-toggle="buttons">' +
+            '<label class="btn btn-secondary active">' +
+            '<input type="radio" name="options" autocomplete="off" data-value="nRF24" > nRF24' +
+            '</label>'+
+            '<label class="btn btn-secondary">' +
+              '<input type="radio" name="options" autocomplete="off" data-value="LT1167_PL8900"> LT1167_PL8900' +
+            '</label>' +
+          '</div>';
+        }
+        else
+        {
+          elmt += '<input type="text" class="form-control" name="' + k + '"/>';
+          elmt += '</div>';
+        }
+
         settings += elmt;
       });
-        
+
       $('#settings').prepend(settings);
       $('#settings').submit(function(e) {
         var obj = {};
-        
+
         FORM_SETTINGS.forEach(function(k) {
           obj[k] = $('#settings input[name="' + k + '"]').val();
         });
-        
+
         // pretty hacky. whatever.
         obj.device_ids = _.map(
           $('.selectize-control .option'),
-          function(x) { 
+          function(x) {
             return $(x).data('value')
           }
         );
-        
+
         $.ajax(
           "/settings",
           {
@@ -576,17 +595,17 @@
             data: JSON.stringify(obj)
           }
         );
-        
+
         e.preventDefault();
         return false;
       });
-      
+
       $('#gateway-server-form').submit(function(e) {
         saveGatewayConfigs();
         e.preventDefault();
         return false;
       });
-      
+
       $('.field-help').each(function() {
         var elmt = $('<i></i>')
           .addClass('glyphicon glyphicon-question-sign')
@@ -597,14 +616,14 @@
           });
         $(this).append(elmt);
       });
-      
+
       $('#updates-btn').click(handleCheckForUpdates);
-      
+
       loadSettings();
       updateModeOptions();
     });
   </script>
-  
+
   <div id="update-firmware-modal" class="modal fade" role="dialog">
     <div class="modal-dialog">
       <!-- Modal content-->
@@ -620,10 +639,10 @@
             <a href="https://github.com/sidoh/esp8266_milight_hub/releases">GitHub releases page</a>.
             Check for a new version by clicking on the "Check for Updates" button.
             </p>
-            
+
             <p>
               <b>Make sure the binary you're uploading was compiled for your board!</b>
-              Firmware with incompatible settings could prevent boots. If this happens, 
+              Firmware with incompatible settings could prevent boots. If this happens,
               reflash the board with USB.
             </p>
           </div>
@@ -637,10 +656,10 @@
           <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
         </div>
       </div>
-      
+
     </div>
   </div>
-  
+
   <div id="updates-modal" class="modal fade" role="dialog">
     <div class="modal-dialog">
       <!-- Modal content-->
@@ -651,29 +670,29 @@
         </div>
         <div class="modal-body">
           <div id="version-summary"></div>
-          
+
           <hr />
-          
+
           <h4>Current Version</h4>
           <div id="current-version"></div>
-          
+
           <div id="latest-version">
             <h4>Latest Version</h4>
             <div class="status"></div>
             <div id="latest-version-info">
               <label>Version</label>
               <div class="info-key" data-key="tag_name"></div>
-              
+
               <label>Release Date</label>
               <div class="info-key" data-key="published_at"></div>
-              
+
               <label>Release Notes</label>
               <pre class="info-key" data-key="body"></pre>
-              
+
               <div>
                 <a class="info-key" data-prop="href" data-key="html_url">View on GitHub</a>
               </div>
-              
+
               <div>
                 <a class="info-key" id="firmware-link">Download Firmware</a>
               </div>
@@ -685,10 +704,10 @@
           <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
         </div>
       </div>
-      
+
     </div>
   </div>
-  
+
   <div class="container">
     <div class="row header-row">
       <div class="col-sm-12">
@@ -697,9 +716,9 @@
         </h1>
       </div>
     </div>
-    
+
     <div>&nbsp;</div>
-    
+
     <div class="row">
       <div class="col-sm-4">
         <label for="deviceId" id="device-id-label">
@@ -709,11 +728,11 @@
         <select id="deviceId" placeholder="Enter hub ID">
 				</select>
       </div>
-      
+
       <div class="col-sm-3">
         <div class="mode-option" id="group-option" data-for="cct,rgbw,rgb_cct">
           <label for="groupId">Group</label>
-        
+
           <div class="btn-group" id="groupId" data-toggle="buttons">
             <label class="btn btn-secondary active">
               <input type="radio" name="options" autocomplete="off" data-value="1" checked> 1
@@ -733,10 +752,10 @@
           </div>
         </div>
       </div>
-      
+
       <div class="col-sm-4">
         <label for="groupId">Mode</label>
-        
+
         <div class="btn-group" id="mode" data-toggle="buttons">
           <label class="btn btn-secondary active">
             <input type="radio" name="mode" autocomplete="off" data-value="rgbw" checked> RGBW
@@ -753,7 +772,7 @@
         </div>
       </div>
     </div>
-    
+
     <div class="row"><div class="col-sm-12">
     <div class="mode-option" data-for="rgbw,rgb_cct,rgb">
       <div class="row">
@@ -761,7 +780,7 @@
           <h5>Hue</h5>
         </div>
       </div>
-      
+
       <div class="row">
         <div class="col-sm-6">
           <span class="hue-picker">
@@ -772,7 +791,7 @@
       </div>
     </div>
     </div></div>
-    
+
     <div class="mode-option" data-for="rgb_cct">
       <div class="row">
         <div class="col-sm-12">
@@ -789,7 +808,7 @@
         </div>
       </div>
     </div>
-          
+
     <div class="mode-option" data-for="cct,rgb_cct">
       <div class="row">
         <div class="col-sm-12">
@@ -806,13 +825,13 @@
         </div>
       </div>
     </div>
-    
+
     <div class="row">
       <div class="col-sm-12">
         <h5>Brightness</h5>
       </div>
     </div>
-      
+
     <div class="row">
       <div class="col-sm-12">
         <input class="slider raw-update" name="level"
@@ -822,13 +841,13 @@
         />
       </div>
     </div>
-    
+
     <div class="row">
       <div class="col-sm-12">
         <h5>Commands</h5>
       </div>
     </div>
-    
+
     <div class="row">
       <div class="col-sm-12">
         <ul class="command-buttons">
@@ -886,12 +905,12 @@
         </ul>
       </div>
     </div>
-    
+
     <div class="row header-row">
       <div class="col col-sm-10">
         <h1>Gateway Servers</h1>
       </div>
-      
+
       <div class="col col-sm-2">
         <button class="btn btn-success header-btn" id="add-server-btn">
           <i class="glyphicon glyphicon-plus"></i>
@@ -899,7 +918,7 @@
         </button>
       </div>
     </div>
-    
+
     <div class="row">
       <div class="col col-sm-12">
         <form id="gateway-server-form">
@@ -918,17 +937,17 @@
         </form>
       </div>
     </div>
-    
+
     <div>&nbsp;</div>
-    
+
     <div class="row header-row">
       <div class="col-sm-12">
         <h1>Settings</h1>
       </div>
     </div>
-    
+
     <div>&nbsp;</div>
-    
+
     <div class="row">
       <div class="col-sm-12">
         <form action="#" id="settings">
@@ -936,19 +955,19 @@
         </form>
       </div>
     </div>
-    
+
     <div class="row header-row">
       <div class="col-sm-12">
         <h1>Sniff Traffic</h1>
       </div>
     </div>
-    
+
     <div>&nbsp;</div>
-    
+
     <div class="row">
       <div class="col-sm-12">
         <button type="button" id="sniff" class="btn btn-primary">Start Sniffing</button>
-        
+
         <div class="btn-group" id="sniff-type" data-toggle="buttons">
           <label class="btn btn-secondary active">
             <input type="radio" name="options" autocomplete="off" data-value="rgbw" checked> RGBW
@@ -963,31 +982,31 @@
             <input type="radio" name="options" autocomplete="off" data-value="rgb"> RGB
           </label>
         </div>
-        
+
         <div> &nbsp; </div>
-        
+
         <pre id="sniffed-traffic"></pre>
       </div>
     </div>
-    
+
     <div class="row header-row">
       <div class="col-sm-12">
         <h1>Admin</h1>
       </div>
     </div>
-    
+
     <div>&nbsp;</div>
-    
+
     <div class="row">
       <div class="col-sm-12">
         <button type="button" class="btn btn-danger system-btn" data-command="restart">
           Restart
         </button>
-        
+
         <button type="button" id="updates-btn" class="btn btn-primary">
           Check for Updates
         </button>
-        
+
         <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#update-firmware-modal">
           Update Firmware
         </button>
@@ -995,4 +1014,4 @@
     </div>
   </div>
 </body>
-</html>
+</html>

+ 36 - 30
lib/MiLight/MiLightClient.cpp

@@ -2,40 +2,42 @@
 #include <MiLightRadioConfig.h>
 #include <Arduino.h>
 
-MiLightRadio* MiLightClient::switchRadio(const MiLightRadioType type) {
+
+MiLightRadioInterface* MiLightClient::switchRadio(const MiLightRadioType type) {
   RadioStack* stack = NULL;
-  
+
   for (int i = 0; i < numRadios; i++) {
     if (radios[i]->config.type == type) {
       stack = radios[i];
       break;
     }
   }
-  
+
   if (stack != NULL) {
-    MiLightRadio *radio = stack->getRadio();
-    
+    MiLightRadioInterface *radio = stack->getRadioInterface();
+
     if (currentRadio->config.type != stack->config.type) {
       radio->configure();
     }
-    
+
     currentRadio = stack;
     formatter = stack->config.packetFormatter;
     return radio;
   } else {
-    Serial.print(F("MiLightClient - tried to get radio for unknown type: "));
+    Serial.print("MiLightClient - tried to get radio for unknown type: ");
     Serial.println(type);
   }
-  
+
   return NULL;
 }
 
-void MiLightClient::prepare(MiLightRadioConfig& config, 
-  const uint16_t deviceId, 
+
+void MiLightClient::prepare(MiLightRadioConfig& config,
+  const uint16_t deviceId,
   const uint8_t groupId) {
-  
+
   switchRadio(config.type);
-  
+
   if (deviceId >= 0 && groupId >= 0) {
     formatter->prepare(deviceId, groupId);
   }
@@ -45,28 +47,29 @@ void MiLightClient::setResendCount(const unsigned int resendCount) {
   this->resendCount = resendCount;
 }
 
+
 bool MiLightClient::available() {
   if (currentRadio == NULL) {
     return false;
   }
-  
-  return currentRadio->getRadio()->available();
-}
 
+  return currentRadio->getRadioInterface()->available();
+}
 void MiLightClient::read(uint8_t packet[]) {
   if (currentRadio == NULL) {
     return;
   }
-  
-  size_t length;
-  currentRadio->getRadio()->read(packet, length);
+
+  size_t length = currentRadio->config.getPacketLength();
+
+  currentRadio->getRadioInterface()->read(packet, length);
 }
 
 void MiLightClient::write(uint8_t packet[]) {
   if (currentRadio == NULL) {
     return;
   }
-  
+
 #ifdef DEBUG_PRINTF
   printf("Sending packet: ");
   for (int i = 0; i < currentRadio->config.getPacketLength(); i++) {
@@ -74,12 +77,15 @@ void MiLightClient::write(uint8_t packet[]) {
   }
   printf("\n");
 #endif
-  
+  int iStart = millis();
   for (int i = 0; i < this->resendCount; i++) {
-    currentRadio->getRadio()->write(packet, currentRadio->config.getPacketLength());
+        currentRadio->getRadioInterface()->write(packet, currentRadio->config.getPacketLength());
   }
+  int iElapsed = millis() - iStart;
+  Serial.print("Elapsed: ");
+  Serial.println(iElapsed);
 }
-    
+
 void MiLightClient::updateColorRaw(const uint8_t color) {
   formatter->updateColorRaw(color);
   flushPacket();
@@ -94,7 +100,7 @@ void MiLightClient::updateBrightness(const uint8_t brightness) {
   formatter->updateBrightness(brightness);
   flushPacket();
 }
-    
+
 void MiLightClient::updateMode(uint8_t mode) {
   formatter->updateMode(mode);
   flushPacket();
@@ -118,7 +124,7 @@ void MiLightClient::modeSpeedUp() {
   formatter->modeSpeedUp();
   flushPacket();
 }
-    
+
 void MiLightClient::updateStatus(MiLightStatus status, uint8_t groupId) {
   formatter->updateStatus(status, groupId);
   flushPacket();
@@ -148,7 +154,7 @@ void MiLightClient::unpair() {
   formatter->unpair();
   flushPacket();
 }
-    
+
 void MiLightClient::increaseBrightness() {
   formatter->increaseBrightness();
   flushPacket();
@@ -182,24 +188,24 @@ void MiLightClient::command(uint8_t command, uint8_t arg) {
 void MiLightClient::formatPacket(uint8_t* packet, char* buffer) {
   formatter->format(packet, buffer);
 }
-    
+
 void MiLightClient::flushPacket() {
   PacketStream& stream = formatter->buildPackets();
   const size_t prevNumRepeats = this->resendCount;
-  
+
   // When sending multiple packets, normalize the number of repeats
   if (stream.numPackets > 1) {
     setResendCount(MILIGHT_DEFAULT_RESEND_COUNT);
   }
-  
+
   while (stream.hasNext()) {
     write(stream.next());
-    
+
     if (stream.hasNext()) {
       delay(10);
     }
   }
-  
+
   setResendCount(prevNumRepeats);
   formatter->reset();
 }

+ 46 - 27
lib/MiLight/MiLightClient.h

@@ -1,9 +1,11 @@
 #include <Arduino.h>
 #include <MiLightRadio.h>
+#include <MiLightRadioPL1167_LT8900.h>
 #include <PL1167_nRF24.h>
 #include <RF24.h>
 #include <MiLightButtons.h>
 #include <RadioStack.h>
+#include <Settings.h>
 
 #ifndef _MILIGHTCLIENT_H
 #define _MILIGHTCLIENT_H
@@ -14,38 +16,53 @@
 
 class MiLightClient {
   public:
-    MiLightClient(uint8_t cePin, uint8_t csnPin)
-      : rf(RF24(cePin, csnPin)),
-      resendCount(MILIGHT_DEFAULT_RESEND_COUNT),
-      currentRadio(NULL),
-      numRadios(MiLightRadioConfig::NUM_CONFIGS)
+  MiLightClient(byte byCSPin, byte byResetPin, byte byPktFlag, eRadioInterfaceType InterfaceType)
+  :
+  resendCount(MILIGHT_DEFAULT_RESEND_COUNT),
+  currentRadio(NULL),
+  numRadios(MiLightRadioConfig::NUM_CONFIGS)
+
+  {
+    radios = new RadioStack*[numRadios];
+
+    for (size_t i = 0; i < numRadios; i++)
     {
-      radios = new RadioStack*[numRadios];
-      
-      for (size_t i = 0; i < numRadios; i++) {
-        radios[i] = new RadioStack(rf, *MiLightRadioConfig::ALL_CONFIGS[i]);
+      if(InterfaceType == LT1167_PL8900)
+      {
+        radios[i] = new RadioStack(byCSPin, byResetPin, byPktFlag, *MiLightRadioConfig::ALL_CONFIGS[i]);
+      }
+      else if(InterfaceType == nRF24)
+      {
+        pRF = new RF24(byCSPin, byPktFlag);
+        radios[i] = new RadioStack(*pRF, *MiLightRadioConfig::ALL_CONFIGS[i]);
       }
-      
-      currentRadio = radios[0];
-      currentRadio->getRadio()->configure();
     }
-    
+
+    currentRadio = radios[0];
+
+    currentRadio->getRadioInterface()->configure();
+  }
+
+
     ~MiLightClient() {
+      delete pRF;
       delete[] radios;
     }
-    
+
     void begin() {
       for (size_t i = 0; i < numRadios; i++) {
-        radios[i]->getRadio()->begin();
+        radios[i]->getRadioInterface()->begin();
       }
     }
-    
+
+
     void prepare(MiLightRadioConfig& config, const uint16_t deviceId = -1, const uint8_t groupId = -1);
+
     void setResendCount(const unsigned int resendCount);
     bool available();
     void read(uint8_t packet[]);
     void write(uint8_t packet[]);
-    
+
     // Common methods
     void updateStatus(MiLightStatus status);
     void updateStatus(MiLightStatus status, uint8_t groupId);
@@ -57,7 +74,7 @@ class MiLightClient {
     void previousMode();
     void modeSpeedDown();
     void modeSpeedUp();
-    
+
     // RGBW methods
     void updateHue(const uint16_t hue);
     void updateBrightness(const uint8_t brightness);
@@ -70,23 +87,25 @@ class MiLightClient {
     void increaseTemperature();
     void increaseBrightness();
     void decreaseBrightness();
-    
+
     void updateSaturation(const uint8_t saturation);
-    
+
     void formatPacket(uint8_t* packet, char* buffer);
-    
-    
+
+
   protected:
-    RF24 rf;
+
+    RF24 *pRF;
     RadioStack** radios;
     RadioStack* currentRadio;
     PacketFormatter* formatter;
     const size_t numRadios;
-    
+
     unsigned int resendCount;
-    
-    MiLightRadio* switchRadio(const MiLightRadioType type);
+
+    MiLightRadioInterface* switchRadio(const MiLightRadioType type);
+
     void flushPacket();
 };
 
-#endif
+#endif

+ 4 - 3
lib/MiLight/MiLightRadio.h

@@ -15,16 +15,17 @@
 
 #include "AbstractPL1167.h"
 #include <MiLightRadioConfig.h>
+#include <MiLightRadioInterface.h>
 
 // #define DEBUG_PRINTF
 
 #ifndef MILIGHTRADIO_H_
 #define MILIGHTRADIO_H_
 
-class MiLightRadio {
+class MiLightRadio : public MiLightRadioInterface{
   public:
     MiLightRadio(AbstractPL1167 &pl1167, const MiLightRadioConfig& config);
-    
+
     int begin();
     bool available();
     int read(uint8_t frame[], size_t &frame_length);
@@ -32,7 +33,7 @@ class MiLightRadio {
     int write(uint8_t frame[], size_t frame_length);
     int resend();
     int configure();
-    
+
   private:
     AbstractPL1167 &_pl1167;
     const MiLightRadioConfig& config;

+ 29 - 0
lib/MiLight/MiLightRadioInterface.h

@@ -0,0 +1,29 @@
+
+#ifdef ARDUINO
+#include "Arduino.h"
+#else
+#include <stdint.h>
+#include <stdlib.h>
+#endif
+
+#ifndef MILIGHTRADIOINTERFACE_H_
+#define MILIGHTRADIOINTERFACE_H_
+
+class MiLightRadioInterface
+{
+  public:
+
+    virtual int begin();
+    virtual bool available();
+    virtual int read(uint8_t frame[], size_t &frame_length);
+    virtual int dupesReceived();
+    virtual int write(uint8_t frame[], size_t frame_length);
+    virtual int resend();
+    virtual int configure();
+
+};
+
+
+
+
+#endif /* MILIGHTRADIOINTERFACE_H_ */

+ 104 - 0
lib/MiLight/MiLightRadioPL1167_LT8900.h

@@ -0,0 +1,104 @@
+/*
+ * MiLightRadio.h
+ *
+ *  Created on: 29 May 2015
+ *      Author: henryk
+ */
+
+#ifdef ARDUINO
+#include "Arduino.h"
+#else
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include <MiLightRadioConfig.h>
+#include <MiLightButtons.h>
+#include <MiLightRadioInterface.h>
+
+/*
+#define MODE_RGB			0
+#define MODE_DUAL_WHITE		1
+#define MODE_DUAL_WHITE_RGB 2
+
+#define MILIGHT_SYNCWORD_RGB 0x258B00000000147A
+#define MILIGHT_SYNCWORD_DUAL_WHITE 0x55AA00000000050A
+#define MILIGHT_SYNCWORD_DUALWHITE_RGB 0x1809000000007236
+*/
+// Register defines
+#define REGISTER_READ       0b10000000  //bin
+#define REGISTER_WRITE      0b00000000  //bin
+#define REGISTER_MASK       0b01111111  //bin
+
+#define R_CHANNEL           7
+#define CHANNEL_RX_BIT      7
+#define CHANNEL_TX_BIT      8
+#define CHANNEL_MASK        0b01111111  ///bin
+
+#define STATUS_PKT_BIT_MASK	0x40
+
+#define R_STATUS            48
+#define STATUS_CRC_BIT      15
+
+#define R_FIFO              50
+#define R_FIFO_CONTROL      52
+
+#define R_SYNCWORD1         36
+#define R_SYNCWORD2         37
+#define R_SYNCWORD3         38
+#define R_SYNCWORD4         39
+
+#define DEFAULT_TIME_BETWEEN_RETRANSMISSIONS_uS	350
+// #define DEBUG_PRINTF
+
+#ifndef MILIGHTRADIOPL1167_LT8900_H_
+#define MILIGHTRADIOPL1167_LT8900_H_
+
+class MiLightRadioPL1167_LT8900 : public MiLightRadioInterface{
+  public:
+    MiLightRadioPL1167_LT8900(byte byCSPin, byte byResetPin, byte byPktFlag, const MiLightRadioConfig& config);
+
+    virtual int begin();
+    virtual bool available();
+    virtual int read(uint8_t frame[], size_t &frame_length);
+    virtual int dupesReceived();
+    virtual int write(uint8_t frame[], size_t frame_length);
+    virtual int resend();
+    virtual int configure();
+
+  private:
+
+
+        void vInitRadioModule(MiLightRadioType type);
+        //void vSetSyncWord(uint64_t syncWord);
+        void vSetSyncWord(uint16_t syncWord3, uint16_t syncWord2, uint16_t syncWord1, uint16_t syncWord0);
+        uint16_t uiReadRegister(uint8_t reg);
+        void regWrite16(byte ADDR, byte V1, byte V2, byte WAIT);
+        uint8_t uiWriteRegister(uint8_t reg, uint16_t data);
+
+        bool bAvailablePin(void);
+        bool bAvailableRegister(void);
+        void vStartListening(uint uiChannelToListenTo);
+        void vResumeRX(void);
+        int iReadRXBuffer(uint8_t *buffer, size_t maxBuffer);
+        void vSetChannel(uint8_t channel);
+        void vGenericSendPacket(int iMode, int iLength, byte *pbyFrame, byte byChannel );
+        bool bCheckRadioConnection(void);
+        bool sendPacket(uint8_t *data, size_t packetSize,byte byChannel);
+
+        byte _pin_pktflag;
+      	byte _csPin;
+
+    const MiLightRadioConfig& config;
+    uint32_t _prev_packet_id;
+    uint8_t _channel = 0;
+    uint8_t _packet[10];
+    uint8_t _out_packet[10];
+    bool _waiting;
+    int _dupes_received;
+};
+
+
+
+#endif /* MILIGHTRADIO_H_ */

+ 631 - 0
lib/MiLight/MiLightRadioPL1197_LT8900.cpp

@@ -0,0 +1,631 @@
+/*
+ * MiLightRadioPL1167_LT89000.cpp
+ *
+ *  Created on: 31 March 2017
+ *      Author: WoodsterDK
+ *
+ *  Very inspired by:
+ *  https://github.com/pmoscetta/authometion-milight/tree/master/Authometion-MiLight
+ *  https://bitbucket.org/robvanderveer/lt8900lib
+ */
+
+#include "MiLightRadioPL1167_LT8900.h"
+#include <SPI.h>
+
+#define DEBUG_PRINTF
+
+/**************************************************************************/
+// Constructor
+/**************************************************************************/
+MiLightRadioPL1167_LT8900::MiLightRadioPL1167_LT8900(byte byCSPin, byte byResetPin, byte byPktFlag, const MiLightRadioConfig& config)
+  :  config(config)
+{
+  _csPin = byCSPin;
+	_pin_pktflag = byPktFlag;
+
+  pinMode(_pin_pktflag, INPUT);
+
+	if (byResetPin > 0)					// If zero then bypass hardware reset
+	{
+		pinMode(byResetPin, OUTPUT);
+		digitalWrite(byResetPin, LOW);
+		delay(200);
+		digitalWrite(byResetPin, HIGH);
+		delay(200);
+	}
+
+  pinMode(_csPin, OUTPUT);
+  digitalWrite(_csPin, HIGH);
+
+  SPI.begin();
+
+  SPI.setFrequency(1000000);
+  SPI.setDataMode(SPI_MODE1);
+  //SPI.setClockDivider(SPI_CLOCK_DIV64); // UNO and 328
+  SPI.setClockDivider(SPI_CLOCK_DIV128); // MEGA and FASTER
+  SPI.setBitOrder(MSBFIRST);
+
+  //Initialize transceiver with correct settings
+  vInitRadioModule(config.type);
+  delay(50);
+
+  // Check if HW is connected
+  bCheckRadioConnection();
+
+  //Reset SPI MODE to default
+  SPI.setDataMode(SPI_MODE0);
+  _waiting = false;
+}
+
+
+
+
+/**************************************************************************/
+// Checks the connection to the radio module by verifying a register setting
+/**************************************************************************/
+bool MiLightRadioPL1167_LT8900::bCheckRadioConnection(void)
+{
+	int iRetValue = 0;
+	uint16_t value_0 = uiReadRegister(0);
+	uint16_t value_1 = uiReadRegister(1);
+
+	if ((value_0 == 0x6fe0) && (value_1 == 0x5681))
+	{
+    #ifdef DEBUG_PRINTF
+		  Serial.println("Radio module running correctly...");
+    #endif
+		iRetValue = 1;
+	}
+	else
+	{
+    #ifdef DEBUG_PRINTF
+		  Serial.println("Failed initializing the radio module...");
+    #endif
+	}
+
+	return iRetValue;
+}
+
+/**************************************************************************/
+// Initialize radio module
+/**************************************************************************/
+void MiLightRadioPL1167_LT8900::vInitRadioModule(MiLightRadioType type)
+{
+	if (type == RGB_CCT)
+	{
+		bool bWriteDefaultDefault = true;  // Is it okay to use the default power up values, without setting them
+
+		regWrite16(0x00, 0x6F, 0xE0, 7);  // Recommended value by PMmicro
+		regWrite16(0x02, 0x66, 0x17, 7);  // Recommended value by PMmicro
+		regWrite16(0x04, 0x9C, 0xC9, 7);  // Recommended value by PMmicro
+
+		regWrite16(0x05, 0x66, 0x37, 7);  // Recommended value by PMmicro
+		regWrite16(0x07, 0x00, 0x4C, 7);  // PL1167's TX/RX Enable and Channel Register, Default channel 76
+		regWrite16(0x08, 0x6C, 0x90, 7);  // Recommended value by PMmicro
+		regWrite16(0x09, 0x48, 0x00, 7);  // PA Control register
+
+		regWrite16(0x0B, 0x00, 0x08, 7);  // Recommended value by PMmicro
+		regWrite16(0x0D, 0x48, 0xBD, 7);  // Recommended value by PMmicro
+		regWrite16(0x16, 0x00, 0xFF, 7);  // Recommended value by PMmicro
+		regWrite16(0x18, 0x00, 0x67, 7);  // Recommended value by PMmicro
+
+		regWrite16(0x1A, 0x19, 0xE0, 7);  // Recommended value by PMmicro
+		regWrite16(0x1B, 0x13, 0x00, 7);  // Recommended value by PMmicro
+
+		regWrite16(0x20, 0x48, 0x00, 7);  // Recommended value by PMmicro
+		regWrite16(0x21, 0x3F, 0xC7, 7);  // Recommended value by PMmicro
+		regWrite16(0x22, 0x20, 0x00, 7);  // Recommended value by PMmicro
+		regWrite16(0x23, 0x03, 0x00, 7);  // Recommended value by PMmicro
+
+		regWrite16(0x24, 0x72, 0x36, 7);  // Sync R0
+		regWrite16(0x27, 0x18, 0x09, 7);  // Sync R3
+		regWrite16(0x28, 0x44, 0x02, 7);  // Recommended value by PMmicro
+		regWrite16(0x29, 0xB0, 0x00, 7);  // Recommended value by PMmicro
+		regWrite16(0x2A, 0xFD, 0xB0, 7);  // Recommended value by PMmicro
+
+		if (bWriteDefaultDefault == true)
+		{
+			regWrite16(0x01, 0x56, 0x81, 7);  // Recommended value by PMmicro
+			regWrite16(0x0A, 0x7F, 0xFD, 7);  // Recommended value by PMmicro
+			regWrite16(0x0C, 0x00, 0x00, 7);  // Recommended value by PMmicro
+			regWrite16(0x17, 0x80, 0x05, 7);  // Recommended value by PMmicro
+			regWrite16(0x19, 0x16, 0x59, 7);  // Recommended value by PMmicro
+			regWrite16(0x1C, 0x18, 0x00, 7);  // Recommended value by PMmicro
+
+			regWrite16(0x25, 0x00, 0x00, 7);  // Recommended value by PMmicro
+			regWrite16(0x26, 0x00, 0x00, 7);  // Recommended value by PMmicro
+			regWrite16(0x2B, 0x00, 0x0F, 7);  // Recommended value by PMmicro
+		}
+	}
+	else if((type == RGBW) || (type == CCT) || (type == RGB) )
+	{
+		regWrite16(0, 111, 224, 7);  // Recommended value by PMmicro
+		regWrite16(1, 86, 129, 7);   // Recommended value by PMmicro
+		regWrite16(2, 102, 23, 7);   // Recommended value by PMmicro
+		regWrite16(4, 156, 201, 7);  // Recommended value by PMmicro
+		regWrite16(5, 102, 55, 7);   // Recommended value by PMmicro
+		regWrite16(7, 0, 76, 7);     // PL1167's TX/RX Enable and Channel Register
+		regWrite16(8, 108, 144, 7);  // Recommended value by PMmicro
+		regWrite16(9, 72, 0, 7);     // PL1167's PA Control Register
+		regWrite16(10, 127, 253, 7); // Recommended value by PMmicro
+		regWrite16(11, 0, 8, 7);     // PL1167's RSSI OFF Control Register -- ???
+		regWrite16(12, 0, 0, 7);     // Recommended value by PMmicro
+		regWrite16(13, 72, 189, 7);  // Recommended value by PMmicro
+		regWrite16(22, 0, 255, 7);   // Recommended value by PMmicro
+		regWrite16(23, 128, 5, 7);   // PL1167's VCO Calibration Enable Register
+		regWrite16(24, 0, 103, 7);   // Recommended value by PMmicro
+		regWrite16(25, 22, 89, 7);   // Recommended value by PMmicro
+		regWrite16(26, 25, 224, 7);  // Recommended value by PMmicro
+		regWrite16(27, 19, 0, 7);    // Recommended value by PMmicro
+		regWrite16(28, 24, 0, 7);    // Recommended value by PMmicro
+		regWrite16(32, 72, 0, 7);    // PL1167's Data Configure Register: LEN_PREAMBLE = 010 -> (0xAAAAAA) 3 bytes, LEN_SYNCWORD = 01 -> 32 bits, LEN_TRAILER = 000 -> (0x05) 4 bits, TYPE_PKT_DAT = 00 -> NRZ law data, TYPE_FEC = 00 -> No FEC
+		regWrite16(33, 63, 199, 7);  // PL1167's Delay Time Control Register 0
+		regWrite16(34, 32, 0, 7);    // PL1167's Delay Time Control Register 1
+		regWrite16(35, 3, 0, 7);     // PL1167's Power Management and Miscellaneous Register
+		regWrite16(40, 68, 2, 7);    // PL1167's FIFO and SYNCWORD Threshold Register
+		regWrite16(41, 176, 0, 7);   // PL1167's Miscellaneous Register: CRC_ON = 1 -> ON, SCR_ON = 0 -> OFF, EN_PACK_LEN = 1 -> ON, FW_TERM_TX = 1 -> ON, AUTO_ACK = 0 -> OFF, PKT_LEVEL = 0 -> PKT active high, CRC_INIT_DAT = 0
+		regWrite16(42, 253, 176, 7); // PL1167's SCAN RSSI Register 0
+		regWrite16(43, 0, 15, 7);    // PL1167's SCAN RSSI Register 1
+		delay(200);
+		regWrite16(128, 0, 0, 7);
+		regWrite16(129, 255, 255, 7);
+		regWrite16(130, 0, 0, 7);
+		regWrite16(132, 0, 0, 7);
+		regWrite16(133, 255, 255, 7);
+		regWrite16(135, 255, 255, 7);
+		regWrite16(136, 0, 0, 7);
+		regWrite16(137, 255, 255, 7);
+		regWrite16(138, 0, 0, 7);
+		regWrite16(139, 255, 255, 7);
+		regWrite16(140, 0, 0, 7);
+		regWrite16(141, 255, 255, 7);
+		regWrite16(150, 0, 0, 7);
+		regWrite16(151, 255, 255, 7);
+		regWrite16(152, 0, 0, 7);
+		regWrite16(153, 255, 255, 7);
+		regWrite16(154, 0, 0, 7);
+		regWrite16(155, 255, 255, 7);
+		regWrite16(156, 0, 0, 7);
+		regWrite16(160, 0, 0, 7);
+		regWrite16(161, 255, 255, 7);
+		regWrite16(162, 0, 0, 7);
+		regWrite16(163, 255, 255, 7);
+		regWrite16(168, 0, 0, 7);
+		regWrite16(169, 255, 255, 7);
+		regWrite16(170, 0, 0, 7);
+		regWrite16(171, 255, 255, 7);
+		regWrite16(7, 0, 0, 7);       // Disable TX/RX and set radio channel to 0
+	}
+}
+
+/**************************************************************************/
+// Set sync word
+/**************************************************************************/
+void MiLightRadioPL1167_LT8900::vSetSyncWord(uint16_t syncWord3, uint16_t syncWord2, uint16_t syncWord1, uint16_t syncWord0)
+{
+	uiWriteRegister(R_SYNCWORD1, syncWord0);
+	uiWriteRegister(R_SYNCWORD2, syncWord1);
+	uiWriteRegister(R_SYNCWORD3, syncWord1);
+	uiWriteRegister(R_SYNCWORD4, syncWord3);
+}
+
+/**************************************************************************/
+// Low level register write with delay
+/**************************************************************************/
+void MiLightRadioPL1167_LT8900::regWrite16(byte ADDR, byte V1, byte V2, byte WAIT)
+{
+	digitalWrite(_csPin, LOW);
+	SPI.transfer(ADDR);
+	SPI.transfer(V1);
+	SPI.transfer(V2);
+	digitalWrite(_csPin, HIGH);
+	delayMicroseconds(WAIT);
+}
+
+
+/**************************************************************************/
+// Low level register read
+/**************************************************************************/
+uint16_t MiLightRadioPL1167_LT8900::uiReadRegister(uint8_t reg)
+{
+	SPI.setDataMode(SPI_MODE1);
+	digitalWrite(_csPin, LOW);
+	SPI.transfer(REGISTER_READ | (REGISTER_MASK & reg));
+	uint8_t high = SPI.transfer(0x00);
+	uint8_t low = SPI.transfer(0x00);
+
+	digitalWrite(_csPin, HIGH);
+
+	SPI.setDataMode(SPI_MODE0);
+	return (high << 8 | low);
+}
+
+
+/**************************************************************************/
+// Low level 16bit register write
+/**************************************************************************/
+uint8_t MiLightRadioPL1167_LT8900::uiWriteRegister(uint8_t reg, uint16_t data)
+{
+	uint8_t high = data >> 8;
+	uint8_t low = data & 0xFF;
+
+	digitalWrite(_csPin, LOW);
+
+	uint8_t result = SPI.transfer(REGISTER_WRITE | (REGISTER_MASK & reg));
+	SPI.transfer(high);
+	SPI.transfer(low);
+
+	digitalWrite(_csPin, HIGH);
+
+	return result;
+}
+
+/**************************************************************************/
+// Start listening on specified channel and syncword
+/**************************************************************************/
+void MiLightRadioPL1167_LT8900::vStartListening(uint uiChannelToListenTo)
+{
+  _dupes_received = 0;
+  vSetSyncWord(config.syncword3, 0,0,config.syncword0);
+	vSetChannel(uiChannelToListenTo);
+
+	uiWriteRegister(R_CHANNEL, _channel & CHANNEL_MASK);   //turn off rx/tx
+	delay(3);
+	uiWriteRegister(R_FIFO_CONTROL, 0x0080);  //flush rx
+	uiWriteRegister(R_CHANNEL, (_channel & CHANNEL_MASK) | _BV(CHANNEL_RX_BIT));   //enable RX
+	delay(5);
+}
+
+/**************************************************************************/
+// Resume listening - without changing the channel and syncword
+/**************************************************************************/
+void MiLightRadioPL1167_LT8900::vResumeRX(void)
+{
+  _dupes_received = 0;
+	uiWriteRegister(R_CHANNEL, _channel & CHANNEL_MASK);   //turn off rx/tx
+	delay(3);
+	uiWriteRegister(R_FIFO_CONTROL, 0x0080);  //flush rx
+	uiWriteRegister(R_CHANNEL, (_channel & CHANNEL_MASK) | _BV(CHANNEL_RX_BIT));   //enable RX
+}
+
+/**************************************************************************/
+// Check if data is available using the hardware pin PKT_FLAG
+/**************************************************************************/
+bool MiLightRadioPL1167_LT8900::bAvailablePin()
+{
+	//read the PKT_FLAG pin.
+	if (digitalRead(_pin_pktflag) != 0)
+	{
+		return true;
+	}
+
+	return false;
+}
+
+/**************************************************************************/
+// Check if data is available using the PKT_FLAG state in the status register
+/**************************************************************************/
+bool MiLightRadioPL1167_LT8900::bAvailableRegister()
+{
+	//read the PKT_FLAG state; this can also be done with a hard wire.
+	uint16_t value = uiReadRegister(R_STATUS);
+
+	if (value & STATUS_PKT_BIT_MASK != 0)
+	{
+		return true;
+	}
+
+	return false;
+}
+
+/**************************************************************************/
+// Read the RX buffer
+/**************************************************************************/
+int MiLightRadioPL1167_LT8900::iReadRXBuffer(uint8_t *buffer, size_t maxBuffer)
+{
+	uint16_t value = uiReadRegister(R_STATUS);
+	if (bitRead(value, STATUS_CRC_BIT) == 0)
+	{
+		uint16_t data = uiReadRegister(R_FIFO);
+		uint8_t packetSize = data >> 8;
+		if (maxBuffer < packetSize + 1)
+		{
+			//BUFFER TOO SMALL
+			return -2;
+		}
+
+		uint8_t pos = 0;;
+		buffer[pos++] = (data & 0xFF);
+		while (pos < packetSize)
+		{
+			data = uiReadRegister(R_FIFO);
+			buffer[pos++] = data >> 8;
+			buffer[pos++] = data & 0xFF;
+		}
+
+		return packetSize;
+	}
+	else
+	{
+		//CRC error
+		return -1;
+	}
+}
+
+
+/**************************************************************************/
+// Set the active channel for the radio module
+/**************************************************************************/
+void MiLightRadioPL1167_LT8900::vSetChannel(uint8_t channel)
+{
+	_channel = channel;
+	uiWriteRegister(R_CHANNEL, (_channel & CHANNEL_MASK));
+}
+
+/**************************************************************************/
+// Startup
+/**************************************************************************/
+int MiLightRadioPL1167_LT8900::begin()
+{
+  vSetChannel(config.channels[0]);
+  configure();
+  available();
+  return 0;
+}
+
+/**************************************************************************/
+// Configure the module according to type, and start listening
+/**************************************************************************/
+int MiLightRadioPL1167_LT8900::configure()
+{
+  vInitRadioModule(config.type);
+  vSetSyncWord(config.syncword3, 0,0,config.syncword0);
+  vStartListening(config.channels[0]);
+  return 0;
+}
+
+/**************************************************************************/
+// Check if data is available
+/**************************************************************************/
+bool MiLightRadioPL1167_LT8900::available()
+{
+  _waiting = false;
+
+  if(bAvailablePin())
+  {
+    int iStartTime = millis();
+    int iUpdateStamp = 0;
+    static byte byLastReceived[32];
+
+    byte byaFramesSizes[20];
+    byte byaFramesReceivedCount[20];
+    byte byaFramesReceived[20][32];
+    byte byFrameCounter = 0;
+
+    bool bDifference = false;
+
+    bool bRetVal = false;
+
+    if (bAvailablePin())
+    {
+      unsigned long ulTimeStamp = millis();
+      unsigned long ulElapsedTime = 0;
+
+      do
+      {
+        if (bAvailablePin())
+        {
+          iUpdateStamp = millis();
+          uint8_t buf[32];
+
+          int packetSize = iReadRXBuffer(buf, 32);
+          if (packetSize > 0)
+          {
+            bRetVal = true;
+            bDifference = false;
+
+            for (int iCounter = 0; iCounter < packetSize && bDifference == false; iCounter++)
+            {
+              if (buf[iCounter] != byLastReceived[iCounter])
+              {
+                bDifference = true;
+              }
+            }
+
+            if (bDifference == true)
+            {
+              for (int i = 0; i < packetSize; i++)
+              {
+                byaFramesReceived[byFrameCounter][i] = buf[i];
+                byLastReceived[i] = buf[i];
+                byaFramesSizes[i] = packetSize;
+              }
+
+              byaFramesReceivedCount[byFrameCounter] = 1;
+              byFrameCounter++;
+            }
+            else
+            {
+              byaFramesReceivedCount[byFrameCounter-1]++;
+              //Serial.print(".");
+            }
+          }
+          else
+          {
+            if (packetSize < 0)
+            {
+              Serial.println(F("Packet less than zero, buffer to small"));
+            }
+            else
+            {
+              Serial.println(F("Packet read fail"));
+            }
+          }
+
+          vResumeRX();
+        }
+
+        ulElapsedTime = millis();
+        yield();
+        ulElapsedTime = ulElapsedTime - ulTimeStamp;
+      }while (ulElapsedTime <1000 );
+
+      Serial.print("ElapsedRX: ");
+      Serial.println(iUpdateStamp - iStartTime);
+
+      if (byFrameCounter != 0)
+      {
+      Serial.println("");
+      Serial.print(F("Packets received: "));
+      Serial.print(byFrameCounter);
+
+      for (byte byCounterFrame = 0; byCounterFrame < byFrameCounter; byCounterFrame++)
+      {
+        _dupes_received = byaFramesReceivedCount[byCounterFrame];
+        Serial.println("");
+        Serial.print(F("Packet read OK, rec: "));
+        Serial.print(byaFramesReceivedCount[byCounterFrame]);
+        Serial.println(F(" Frame: "));
+        //dump the packet.
+
+          _packet[0]=byaFramesSizes[byCounterFrame];
+          for (int iByteCounter = 0; iByteCounter < byaFramesSizes[byCounterFrame]; iByteCounter++)
+          {
+            byte byReceivedvalue = byaFramesReceived[byCounterFrame][iByteCounter];
+            _packet[iByteCounter+1] = byReceivedvalue;
+
+            String stringOne = String(byReceivedvalue, HEX);
+            String stringToWrite = "0x";
+
+            if (byReceivedvalue < 0x10)
+            {
+              stringToWrite += "0";
+            }
+            stringToWrite += stringOne;
+            stringToWrite += " ";
+
+
+            Serial.print(stringToWrite);
+          }
+
+          _waiting = true;
+        }
+        Serial.println("");
+      }
+    }
+    yield();
+  }
+
+  return _waiting;
+}
+
+int MiLightRadioPL1167_LT8900::dupesReceived()
+{
+  return _dupes_received;
+}
+
+/**************************************************************************/
+// Read received data from buffer to upper layer
+/**************************************************************************/
+int MiLightRadioPL1167_LT8900::read(uint8_t frame[], size_t &frame_length)
+{
+  if (!_waiting)
+  {
+    frame_length = 0;
+    return -1;
+  }
+
+  if (frame_length > sizeof(_packet) - 1)
+  {
+    frame_length = sizeof(_packet) - 1;
+  }
+
+  if (frame_length > _packet[0])
+  {
+    frame_length = _packet[0];
+  }
+
+  memcpy(frame, _packet +1 , frame_length);
+  _waiting = false;
+
+  // Start RX mode again
+  vResumeRX();
+
+  return _packet[0];
+}
+
+/**************************************************************************/
+// Write data
+/**************************************************************************/
+int MiLightRadioPL1167_LT8900::write(uint8_t frame[], size_t frame_length)
+{
+  if (frame_length > sizeof(_out_packet) - 1) {
+    return -1;
+  }
+
+  memcpy(_out_packet + 1, frame, frame_length);
+  _out_packet[0] = frame_length;
+
+  SPI.setDataMode(SPI_MODE1);
+
+  int retval = resend();
+  yield();
+
+  SPI.setDataMode(SPI_MODE0);
+
+  if (retval < 0) {
+    return retval;
+  }
+  return frame_length;
+}
+
+/**************************************************************************/
+// Handle the transmission to regarding to freq diversity and repeats
+/**************************************************************************/
+int MiLightRadioPL1167_LT8900::resend()
+{
+  byte Length =  _out_packet[0];
+
+  for (size_t i = 0; i < MiLightRadioConfig::NUM_CHANNELS; i++)
+  {
+    sendPacket(_out_packet, Length, config.channels[i]);
+    delayMicroseconds(DEFAULT_TIME_BETWEEN_RETRANSMISSIONS_uS);
+  }
+
+  return 0;
+}
+
+/**************************************************************************/
+// The actual transmit happens here
+/**************************************************************************/
+bool MiLightRadioPL1167_LT8900::sendPacket(uint8_t *data, size_t packetSize, byte byChannel)
+{
+  if (packetSize < 1 || packetSize > 255)
+  {
+    return false;
+  }
+
+  uiWriteRegister(R_CHANNEL, 0x0000);
+  uiWriteRegister(R_FIFO_CONTROL, 0x8080);  //flush tx and RX
+
+  digitalWrite(_csPin, LOW);        // Enable PL1167 SPI transmission
+  SPI.transfer(R_FIFO);             // Start writing PL1167's FIFO Data register
+  SPI.transfer(packetSize);         // Length of data buffer: x bytes
+
+  for (byte iCounter = 0; iCounter < packetSize; iCounter++)
+  {
+    SPI.transfer((data[1+iCounter]));
+  }
+  digitalWrite(_csPin, HIGH);  // Disable PL1167 SPI transmission
+  delayMicroseconds(10);
+
+  uiWriteRegister(R_CHANNEL,  (byChannel & CHANNEL_MASK) | _BV(CHANNEL_TX_BIT));   //enable RX
+
+  //Wait until the packet is sent.
+  while (digitalRead(_pin_pktflag) == 0)
+  {
+      //do nothing.
+  }
+
+  return true;
+}

+ 32 - 10
lib/MiLight/RadioStack.h

@@ -2,33 +2,55 @@
 #include <PL1167_nRF24.h>
 #include <MiLightRadioConfig.h>
 #include <MiLightRadio.h>
+#include <MiLightRadioPL1167_LT8900.h>
+#include <MiLightRadioInterface.h>
+#include <Settings.h>
 
 #ifndef _RADIO_STACK_H
-#define _RADIO_STACK_H 
+#define _RADIO_STACK_H
 
 class RadioStack {
 public:
-  RadioStack(RF24& rf, const MiLightRadioConfig& config) 
-    : config(config)
+  RadioStack(RF24& rf, const MiLightRadioConfig& config)
+    : config(config),UsedInterfaceType(nRF24)
   {
     nrf = new PL1167_nRF24(rf);
     radio = new MiLightRadio(*nrf, config);
   }
-  
+
+  RadioStack(byte byCSPin, byte byResetPin, byte byPktFlag, const MiLightRadioConfig& config)
+      : config(config),UsedInterfaceType(LT1167_PL8900)
+    {
+      radioPL1167_LT8900 = new MiLightRadioPL1167_LT8900(byCSPin, byResetPin, byPktFlag, config);
+    }
+
   ~RadioStack() {
     delete radio;
     delete nrf;
+    delete radioPL1167_LT8900;
+
   }
-  
-  inline MiLightRadio* getRadio() {
-    return this->radio;
+
+  inline MiLightRadioInterface* getRadioInterface()
+  {
+    if(UsedInterfaceType == nRF24)
+    {
+      return this->radio;
+    }
+    else if(UsedInterfaceType == LT1167_PL8900)
+    {
+      return this->radioPL1167_LT8900;
+    }
   }
-  
+
   const MiLightRadioConfig& config;
-  
+
 private:
   PL1167_nRF24 *nrf;
   MiLightRadio *radio;
+  MiLightRadioPL1167_LT8900 *radioPL1167_LT8900;
+  eRadioInterfaceType UsedInterfaceType;
+
 };
 
-#endif
+#endif

+ 68 - 22
lib/Settings/Settings.cpp

@@ -3,7 +3,7 @@
 #include <FS.h>
 #include <IntParsing.h>
 #include <algorithm>
-  
+
 bool Settings::hasAuthSettings() {
   return adminUsername.length() > 0 && adminPassword.length() > 0;
 }
@@ -16,7 +16,7 @@ size_t Settings::getAutoRestartPeriod() {
   if (_autoRestartPeriod == 0) {
     return 0;
   }
-  
+
   return std::max(_autoRestartPeriod, static_cast<size_t>(MINIMUM_RESTART_PERIOD));
 }
 
@@ -31,34 +31,51 @@ void Settings::deserialize(Settings& settings, JsonObject& parsedSettings) {
     if (parsedSettings.containsKey("admin_username")) {
       settings.adminUsername = parsedSettings.get<String>("admin_username");
     }
-    
+
     if (parsedSettings.containsKey("admin_password")) {
       settings.adminPassword = parsedSettings.get<String>("admin_password");
     }
-    
+
     if (parsedSettings.containsKey("ce_pin")) {
       settings.cePin = parsedSettings["ce_pin"];
     }
-    
+
     if (parsedSettings.containsKey("csn_pin")) {
       settings.csnPin = parsedSettings["csn_pin"];
     }
-    
+
+    if (parsedSettings.containsKey("reset_pin")) {
+      settings.resetPin = parsedSettings["reset_pin"];
+    }
+
+    if (parsedSettings.containsKey("radio_interface_type"))
+    {
+      String InterfaceType = parsedSettings["radio_interface_type"];
+      if(InterfaceType == "nRF24")
+      {
+        settings.radioInterfaceType =  nRF24;
+      }
+      else if(InterfaceType == "nRF24")
+      {
+        settings.radioInterfaceType =  LT1167_PL8900;
+      }
+    }
+
     if (parsedSettings.containsKey("packet_repeats")) {
       settings.packetRepeats = parsedSettings["packet_repeats"];
     }
-    
+
     if (parsedSettings.containsKey("http_repeat_factor")) {
       settings.httpRepeatFactor = parsedSettings["http_repeat_factor"];
     }
-    
+
     if (parsedSettings.containsKey("auto_restart_period")) {
       settings._autoRestartPeriod = parsedSettings["auto_restart_period"];
     }
-    
+
     JsonArray& arr = parsedSettings["device_ids"];
     settings.updateDeviceIds(arr);
-    
+
     JsonArray& gatewayArr = parsedSettings["gateway_configs"];
     settings.updateGatewayConfigs(gatewayArr);
   }
@@ -69,7 +86,7 @@ void Settings::updateDeviceIds(JsonArray& arr) {
     if (this->deviceIds) {
       delete this->deviceIds;
     }
-    
+
     this->deviceIds = new uint16_t[arr.size()];
     this->numDeviceIds = arr.size();
     arr.copyTo(this->deviceIds, arr.size());
@@ -81,13 +98,13 @@ void Settings::updateGatewayConfigs(JsonArray& arr) {
     if (this->gatewayConfigs) {
       delete[] this->gatewayConfigs;
     }
-    
+
     this->gatewayConfigs = new GatewayConfig*[arr.size()];
     this->numGatewayConfigs = arr.size();
-    
+
     for (size_t i = 0; i < arr.size(); i++) {
       JsonArray& params = arr[i];
-      
+
       if (params.success() && params.size() == 3) {
         this->gatewayConfigs[i] = new GatewayConfig(parseInt<uint16_t>(params[0]), params[1], params[2]);
       } else {
@@ -112,6 +129,24 @@ void Settings::patch(JsonObject& parsedSettings) {
     if (parsedSettings.containsKey("csn_pin")) {
       this->csnPin = parsedSettings["csn_pin"];
     }
+
+    if (parsedSettings.containsKey("reset_pin")) {
+      this->resetPin = parsedSettings["reset_pin"];
+    }
+
+    if (parsedSettings.containsKey("radio_interface_type"))
+    {
+      String InterfaceType = parsedSettings["radio_interface_type"];
+      if(InterfaceType == "nRF24")
+      {
+        this->radioInterfaceType =  nRF24;
+      }
+      else if(InterfaceType == "LT1167_PL8900")
+      {
+        this->radioInterfaceType =  LT1167_PL8900;
+      }
+    }
+
     if (parsedSettings.containsKey("packet_repeats")) {
       this->packetRepeats = parsedSettings["packet_repeats"];
     }
@@ -137,7 +172,7 @@ void Settings::load(Settings& settings) {
     File f = SPIFFS.open(SETTINGS_FILE, "r");
     String settingsContents = f.readStringUntil(SETTINGS_TERMINATOR);
     f.close();
-    
+
     deserialize(settings, settingsContents);
   } else {
     settings.save();
@@ -153,7 +188,7 @@ String Settings::toJson(const bool prettyPrint) {
 
 void Settings::save() {
   File f = SPIFFS.open(SETTINGS_FILE, "w");
-  
+
   if (!f) {
     Serial.println(F("Opening settings file failed"));
   } else {
@@ -165,21 +200,32 @@ void Settings::save() {
 void Settings::serialize(Stream& stream, const bool prettyPrint) {
   DynamicJsonBuffer jsonBuffer;
   JsonObject& root = jsonBuffer.createObject();
-  
+
   root["admin_username"] = this->adminUsername;
   root["admin_password"] = this->adminPassword;
   root["ce_pin"] = this->cePin;
   root["csn_pin"] = this->csnPin;
+  root["reset_pin"] = this->resetPin;
+
+  if(this->radioInterfaceType == nRF24)
+  {
+    root["radio_interface_type"] = "nRF24";
+  }
+  else if(this->radioInterfaceType == LT1167_PL8900)
+  {
+    root["radio_interface_type"] = "LT1167_PL8900";
+  }
+
   root["packet_repeats"] = this->packetRepeats;
   root["http_repeat_factor"] = this->httpRepeatFactor;
   root["auto_restart_period"] = this->_autoRestartPeriod;
-  
+
   if (this->deviceIds) {
     JsonArray& arr = jsonBuffer.createArray();
     arr.copyFrom(this->deviceIds, this->numDeviceIds);
     root["device_ids"] = arr;
   }
-  
+
   if (this->gatewayConfigs) {
     JsonArray& arr = jsonBuffer.createArray();
     for (size_t i = 0; i < this->numGatewayConfigs; i++) {
@@ -189,13 +235,13 @@ void Settings::serialize(Stream& stream, const bool prettyPrint) {
       elmt.add(this->gatewayConfigs[i]->protocolVersion);
       arr.add(elmt);
     }
-    
+
     root["gateway_configs"] = arr;
   }
-  
+
   if (prettyPrint) {
     root.prettyPrintTo(stream);
   } else {
     root.printTo(stream);
   }
-}
+}

+ 18 - 8
lib/Settings/Settings.h

@@ -24,14 +24,20 @@
 
 #define MINIMUM_RESTART_PERIOD 1
 
+enum eRadioInterfaceType
+{
+  nRF24 = 0,
+  LT1167_PL8900 =1,
+};
+
 class GatewayConfig {
 public:
-  GatewayConfig(uint16_t deviceId, uint16_t port, uint8_t protocolVersion) 
+  GatewayConfig(uint16_t deviceId, uint16_t port, uint8_t protocolVersion)
     : deviceId(deviceId),
       port(port),
       protocolVersion(protocolVersion)
     { }
-  
+
   const uint16_t deviceId;
   const uint16_t port;
   const uint8_t protocolVersion;
@@ -45,6 +51,8 @@ public:
     // CE and CSN pins from nrf24l01
     cePin(D0),
     csnPin(D8),
+    resetPin(0),
+    radioInterfaceType(LT1167_PL8900),
     deviceIds(NULL),
     gatewayConfigs(NULL),
     numDeviceIds(0),
@@ -53,13 +61,13 @@ public:
     httpRepeatFactor(5),
     _autoRestartPeriod(0)
   { }
-  
+
   ~Settings() {
     if (deviceIds) {
       delete deviceIds;
     }
   }
-  
+
   bool hasAuthSettings();
   bool isAutoRestartEnabled();
   size_t getAutoRestartPeriod();
@@ -67,27 +75,29 @@ public:
   static void deserialize(Settings& settings, String json);
   static void deserialize(Settings& settings, JsonObject& json);
   static void load(Settings& settings);
-  
+
   void save();
   String toJson(const bool prettyPrint = true);
   void serialize(Stream& stream, const bool prettyPrint = false);
   void updateDeviceIds(JsonArray& arr);
   void updateGatewayConfigs(JsonArray& arr);
   void patch(JsonObject& obj);
-  
+
   String adminUsername;
   String adminPassword;
   uint8_t cePin;
   uint8_t csnPin;
+  uint8_t resetPin;
+  eRadioInterfaceType radioInterfaceType;
   uint16_t *deviceIds;
   GatewayConfig **gatewayConfigs;
   size_t numGatewayConfigs;
   size_t numDeviceIds;
   size_t packetRepeats;
   size_t httpRepeatFactor;
-  
+
 protected:
   size_t _autoRestartPeriod;
 };
 
-#endif 
+#endif

+ 6 - 5
platformio.ini

@@ -10,13 +10,14 @@
 
 [common]
 board_f_cpu = 160000000L
-lib_deps_builtin = 
+lib_deps_builtin =
   SPI
-lib_deps_external = 
+lib_deps_external =
   RF24
   WiFiManager
   ArduinoJson
-build_flags = !echo -D MILIGHT_HUB_VERSION=\\\"$(git describe --always)\\\"
+build_flags = !echo -D MILIGHT_HUB_VERSION="\"$(git describe --always)\""
+//build_flags = -D MILIGHT_HUB_VERSION=\"1.1.0\" -D MILIGHT_UDP_DEBUG
 # -D MILIGHT_UDP_DEBUG
 
 [env:nodemcuv2]
@@ -26,7 +27,7 @@ board = nodemcuv2
 lib_deps =
   ${common.lib_deps_builtin}
   ${common.lib_deps_external}
-build_flags = ${common.build_flags} -D FIRMWARE_VARIANT=\\\"nodemcuv2\\\"
+build_flags = ${common.build_flags} -D FIRMWARE_VARIANT="\"nodemcuv2\""
 
 [env:d1_mini]
 platform = espressif8266
@@ -35,7 +36,7 @@ board = d1_mini
 lib_deps =
   ${common.lib_deps_builtin}
   ${common.lib_deps_external}
-build_flags = ${common.build_flags} -D FIRMWARE_VARIANT=\\\"d1_mini\\\"
+build_flags = ${common.build_flags} -D FIRMWARE_VARIANT="\"d1_mini\""
 
 [env:esp12]
 platform = espressif8266

+ 23 - 15
src/main.cpp

@@ -29,13 +29,13 @@ void initMilightUdpServers() {
         delete udpServers[i];
       }
     }
-    
+
     delete udpServers;
   }
-  
+
   udpServers = new MiLightUdpServer*[settings.numGatewayConfigs];
   numUdpServers = settings.numGatewayConfigs;
-  
+
   for (size_t i = 0; i < settings.numGatewayConfigs; i++) {
     GatewayConfig* config = settings.gatewayConfigs[i];
     MiLightUdpServer* server = MiLightUdpServer::fromVersion(
@@ -44,7 +44,7 @@ void initMilightUdpServers() {
       config->port,
       config->deviceId
     );
-    
+
     if (server == NULL) {
       Serial.print(F("Error creating UDP server with protocol version: "));
       Serial.println(config->protocolVersion);
@@ -55,17 +55,25 @@ void initMilightUdpServers() {
   }
 }
 
-void initMilightClient() {
+
+void applySettings() 
+{
   if (milightClient) {
     delete milightClient;
   }
-  
-  milightClient = new MiLightClient(settings.cePin, settings.csnPin);
-  milightClient->begin();
-}
 
-void applySettings() {
-  initMilightClient();
+  if(settings.radioInterfaceType == nRF24)
+  {
+      Serial.println("Starting using 'nRF24' interface...");
+      milightClient = new MiLightClient(settings.cePin, settings.resetPin, settings.csnPin, nRF24);
+      milightClient->begin();
+  }
+  else if(settings.radioInterfaceType == LT1167_PL8900)
+  {
+      Serial.println("Starting using 'PL1167_LT8900' interface...");
+      milightClient = new MiLightClient(settings.cePin, settings.resetPin, settings.csnPin, LT1167_PL8900);
+      milightClient->begin();
+  }
   initMilightUdpServers();
 }
 
@@ -73,7 +81,7 @@ bool shouldRestart() {
   if (! settings.isAutoRestartEnabled()) {
     return false;
   }
-  
+
   return settings.getAutoRestartPeriod()*60*1000 < millis();
 }
 
@@ -83,7 +91,7 @@ void setup() {
   SPIFFS.begin();
   Settings::load(settings);
   applySettings();
-  
+
   httpServer = new MiLightHttpServer(settings, milightClient);
   httpServer->onSettingsSaved(applySettings);
   httpServer->begin();
@@ -91,13 +99,13 @@ void setup() {
 
 void loop() {
   httpServer->handleClient();
-  
+
   if (udpServers) {
     for (size_t i = 0; i < settings.numGatewayConfigs; i++) {
       udpServers[i]->handleClient();
     }
   }
-  
+
   if (shouldRestart()) {
     Serial.println(F("Auto-restart triggered. Restarting..."));
     ESP.restart();