'use strict';

goog.provide('Blockly.Python.third_party');
goog.require('Blockly.Python');

Blockly.Python['sonar_setup'] = function(block) {
    Blockly.Python.addInclude('NewPing', '#include <NewPing.h>');
    let sName = 'sonar' + block.getFieldValue('NUMBER');
    let trig_pin = block.getFieldValue('TRIG_PIN');
    let echo_pin = block.getFieldValue('ECHO_PIN');
    Blockly.Python.reservePin(
        block, trig_pin, Blockly.Python.PinTypes.OUTPUT, 'Sonar_Trig_Pin' + trig_pin);
    Blockly.Python.reservePin(
        block, echo_pin, Blockly.Python.PinTypes.OUTPUT, 'Sonar_Echo_Pin' + echo_pin);
    var maxdist = block.getFieldValue('MAXDIST');

    let trigName = 'TRIG_' + trig_pin;
    let echoName = 'ECHO_' + echo_pin;
    let maxDistName = 'MAXDIST_' + trig_pin + '_' + echo_pin;

    var sonar_def = '#define ' + trigName + '    ' + trig_pin + '\n' +
        '#define ' + echoName + '    ' + echo_pin + '\n' +
        '#define ' + maxDistName + '    ' + maxdist + '\n' +
        'NewPing ' + sName + '(' + trigName + ', ' + echoName + ', ' + maxDistName + ');\n';
    Blockly.Python.addDeclaration('define_' + sName, sonar_def);
    return '';
}

Blockly.Python['sonar_read_dist'] = function(block) {
    let sName = 'sonar' + block.getFieldValue('NUMBER');

    var code = sName + '.ping_cm()';
    return [code, Blockly.Python.ORDER_ATOMIC];
}

Blockly.Python['infraredRay_setup'] = function(block) {
    Blockly.Python.addInclude('IRLib', '' +
        '#include <IRLibDecodeBase.h>\n' +
        '#include <IRLib_P01_NEC.h>\n' +
        '#include <IRLibCombo.h>\n' +
        'IRdecode myDecoder;\n' +
        '#include <IRLibRecv.h>\n' +
        'IRrecv myReceiver(A2);\n' +
        '');

    var IR_keys_def = '#define KEYPAD_UP         0xFF18E7\n' +
        '#define KEYPAD_DOWN       0xFF4AB5\n' +
        '#define KEYPAD_LEFT       0xFF10EF\n' +
        '#define KEYPAD_RIGHT      0xFF5AA5\n' +
        '#define KEYPAD_OK         0xFF38C7\n' +
        '#define KEYPAD_1          0xFFA25D\n' +
        '#define KEYPAD_2          0xFF629D\n' +
        '#define KEYPAD_3          0xFFE21D\n' +
        '#define KEYPAD_4          0xFF22DD\n' +
        '#define KEYPAD_5          0xFF02FD\n' +
        '#define KEYPAD_6          0xFFC23D\n' +
        '#define KEYPAD_7          0xFFE01F\n' +
        '#define KEYPAD_8          0xFFA857\n' +
        '#define KEYPAD_9          0xFF906F\n' +
        '#define KEYPAD_0          0xFF9867\n' +
        '#define KEYPAD_STAR       0xFF6897\n' +
        '#define KEYPAD_NUMSIGN    0xFFB04F\n';
    Blockly.Python.addDeclaration('IR_keys_def', IR_keys_def);

    var IR_setup = 'Serial.begin(9600);\n' +
        'delay(2000);\n' +
        'myReceiver.enableIRIn();';

    Blockly.Python.addSetup('IR_setup', IR_setup, false);

    var code = '' +
        'if (myReceiver.getResults()) {\n' +
        'myDecoder.decode(); \n' +
        '// myDecoder.dumpResults(true);\n' +
        'myReceiver.enableIRIn();\n' +
        '}\n' +
        '';
    return code;
};

Blockly.Python['infraredRay_receive_val'] = function(block) {
    var code = 'myDecoder.value';
    return [code, Blockly.Python.ORDER_ATOMIC];
};

Blockly.Python['infraredRay_send_val'] = function(block) {
    var dropdown_valtype = block.getFieldValue('VALTYPE');
    var code = dropdown_valtype;
    return [code, Blockly.Python.ORDER_ATOMIC];
};

/* RTC 
 *  Setup 
 */
Blockly.Python['RTC_setup'] = function(block) {
    Blockly.Python.addInclude('RTC_include', '#include <Wire.h> //include Wire.h library \n' +
        '#include "RTClib.h" //include Adafruit RTC library');
    Blockly.Python.addDeclaration("RTC_declaration", 'RTC_DS3231 rtc; //Make a RTC DS3231 object\n' +
        ' //Set the names of days\n' +
        'char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};')
    Blockly.Python.addSetup("RTC_setup", ' Serial.begin(9600);\n' +
        '  if (! rtc.begin()) {\n' +
        '    Serial.println("Couldn\'t find RTC");\n' +
        '    while (1);\n' +
        '  }\n' +
        '  //Setup of time if RTC lost power or time is not set\n' +
        '  if (rtc.lostPower()) {\n' +
        '    //Sets the code compilation time to RTC DS3231\n' +
        '    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));\n' +
        '  }\n');
    var code = "DateTime now = rtc.now();\n";
    return code;
}


/* RTC 
 *  Set Date/Week/Time 
 */
Blockly.Python['RTC_setDateTime'] = function(block) {
    var rtc_hour = block.getFieldValue('hour');
    var rtc_min = block.getFieldValue('minute');
    var rtc_sec = block.getFieldValue('second');
    var rtc_year = block.getFieldValue('year');
    var rtc_month = block.getFieldValue('month');
    var rtc_day = block.getFieldValue('day');
    Blockly.Python.addSetup("RTC_set", "rtc.adjust(DateTime(" + rtc_year + "," + rtc_month + "," + rtc_day + "," + rtc_hour + "," + rtc_min + "," + rtc_sec + "));");
    return "";
}

/* RTC 
 *  get Date
 */
Blockly.Python['RTC_getDate'] = function(block) {
    var detail = block.getFieldValue("date_detail");
    var code = "";
    switch (detail) {
        case "year":
            code = "now.year()";
            break;
        case "month":
            code = "now.month()";
            break;
        case "day":
            code = "now.day()";
            break;
        default:
            break;
    }
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* RTC 
 *  get Time
 */
Blockly.Python['RTC_getTime'] = function(block) {
    var detail = block.getFieldValue("time_detail");
    var code = "";
    switch (detail) {
        case "hour":
            code = "now.hour()";
            break;
        case "minute":
            code = "now.minute()";
            break;
        case "second":
            code = "now.second()";
            break;
        default:
            break;
    }
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* RTC 
 *  get Week
 */
Blockly.Python['RTC_getWeek'] = function(block) {
    var code = "daysOfTheWeek[now.dayOfTheWeek()]";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* PulseSensor */
Blockly.Python['PulseSensor_setup'] = function(block) {
    var pin = block.getFieldValue("PIN")
    Blockly.Python.addInclude("PulseSensor_inc", "#define USE_ARDUINO_INTERRUPTS true\n" +
        "#include <PulseSensorPlayground.h>");
    Blockly.Python.addDeclaration("PulseSensor_dec", "const int OUTPUT_TYPE = SERIAL_PLOTTER;\n" +
        "const int PIN_INPUT = " + pin + ";\n" +
        "const int THRESHOLD = 550;\n" + // Adjust this number to avoid noise when idle
        "PulseSensorPlayground pulseSensor;");

    Blockly.Python.addSetup("PulseSensor_setup", "pulseSensor.analogInput(PIN_INPUT);\n" +
        "  pulseSensor.setSerial(Serial);\n" +
        "  pulseSensor.setOutputType(OUTPUT_TYPE);\n" +
        "  pulseSensor.setThreshold(THRESHOLD);\n" +
        "  if (!pulseSensor.begin())\n" +
        "  {\n" +
        "    for (;;) {}\n" +
        "  }");
    return "";
}
/* PulseSensor */
Blockly.Python['PulseSensor_getBPM'] = function(block) {
    var code = "pulseSensor.getBeatsPerMinute()";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* PulseSensor */
Blockly.Python['PulseSensor_Heart_Beats'] = function(block) {
    var code = "pulseSensor.sawStartOfBeat()";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* PulseSensor */
Blockly.Python['PulseSensor_Heart_noBeats'] = function(block) {
    var code = "pulseSensor.isInsideBeat() == false";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* PulseSensor */
Blockly.Python['PulseSensor_print'] = function(block) {
    var code = "pulseSensor.outputSample();\n";
    return code;
}

/*Encoder*/
Blockly.Python['Encoder_Setup'] = function(block) {
    var pin = block.getFieldValue("PIN");
    Blockly.Python.addDeclaration("Encoder_dec", "int encoderCounter = 0;\n" +
        "unsigned long encoderTime = 0, old_encoderTime = 0;\n" +
        "unsigned long encoderTime1 = 0;\n" +
        "float encoderSpeed;\n")
    var setup = "Serial.begin(9600);\n" +
        "attachInterrupt(" + pin + ", encoderCount_CallBack, FALLING);\n";
    Blockly.Python.addSetup("Encoder_setup", setup);
    var func = "bool SpeedDetection()\n" +
        "{\n" +
        "  encoderTime = millis();\n" +
        "  if (abs(encoderTime - old_encoderTime) >= 1000)\n" +
        "  {\n" +
        "    detachInterrupt(" + pin + ");\n" +
        "    encoderSpeed = (float)encoderCounter * 60 / 20;\n" +
        "    encoderCounter = 0;\n" +
        "    old_encoderTime =  millis();\n" +
        "    attachInterrupt(" + pin + ", encoderCount_CallBack, FALLING); \n" +
        "    return 1;\n" +
        "  }\n" +
        "  else\n" +
        "    return 0;\n" +
        "}\n\n" +
        "void encoderCount_CallBack()\n" +
        "{\n" +
        "  encoderCounter++;\n" +
        "}";
    Blockly.Python.addFunction("Encoder_func", func);
    var code = "SpeedDetection();\n";
    return code;
}

/*Encoder*/
Blockly.Python['Encoder_getRotationSpeed'] = function(block) {
    var code = "encoderSpeed";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* RFID 
 *  Setup
 */
Blockly.Python['RFID_Setup'] = function(block) {
    Blockly.Python.addInclude('RFID_include', '#include <SPI.h>\n' +
        '#include <MFRC522.h>');
    Blockly.Python.addDeclaration('RFID_dec', '#define SS_PIN SS\n' +
        'MFRC522 rfid(SS_PIN); // Instance of the class\n' +
        'MFRC522::MIFARE_Key key;\n' +
        'byte nuidPICC[4];\n' +
        'char NUID[4];\n' +
        'String nuid_str="null";');
    Blockly.Python.addSetup('RFID_setup', 'Serial.begin(9600);\n' +
        'SPI.begin(); // Init SPI bus\n' +
        'rfid.PCD_Init(); // Init MFRC522\n' +
        'for (byte i = 0; i < 6; i++) {\n' +
        '  key.keyByte[i] = 0xFF;\n' +
        '}\n' +
        'Serial.println(F("This code scan the MIFARE Classsic NUID."));\n' +
        'Serial.print(F("Using the following key:"));\n' +
        'printHex(key.keyByte, MFRC522::MF_KEY_SIZE);\n');
    Blockly.Python.addFunction("RFID_printHex", 'void printHex(byte *buffer, byte bufferSize) {\n' +
        '  for (byte i = 0; i < bufferSize; i++) {\n' +
        //Serial.print(buffer[i] < 0x10 ? " 0" : " ");
        '    Serial.print(buffer[i], HEX);\n' +
        '  }\n' +
        '}');
    Blockly.Python.addFunction("RFID_tohex", 'String tohex(int n) {\n' +
        '  if (n == 0) {\n' +
        '    return "00"; //n为0\n' +
        '  }\n' +
        '  String result = "";\n' +
        '  char _16[] = {\'0\',\'1\',\'2\',\'3\',\'4\',\'5\',\'6\',\'7\', \'8\',' +
        '\'9\',\'A\',\'B\',\'C\',\'D\',\'E\',\'F\'};\n' +
        '  const int radix = 16;\n' +
        '  while (n) {\n' +
        '    int i = n % radix;\n' +
        '    result = _16[i] + result;\n' +
        '    n /= radix;\n' +
        '  }\n' +
        '  if (result.length() < 2) {\n' +
        '    result = \'0\' + result;\n' +
        '  }\n' +
        '  return result;\n' +
        '}');
    var code = '// Look for new cards\n' +
        'if (!rfid.PICC_IsNewCardPresent())\n' +
        '    return;\n' +
        // Verify if the NUID has been readed
        'if (!rfid.PICC_ReadCardSerial())\n' +
        '  return;\n' +
        'MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);\n' +
        '// Check is the PICC of Classic MIFARE type\n' +
        'if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&\n' +
        '    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&\n' +
        '    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {\n' +
        '    Serial.println(F("Your tag is not supported"));\n' +
        '    return;\n' +
        '}\n' +
        '// Store NUID into nuidPICC array\n' +
        'for (byte i = 0; i < 4; i++) {\n' +
        '    nuidPICC[i] = rfid.uid.uidByte[i];\n' +
        '}\n' +
        '//Store NUID into nuid_str\n' +
        'nuid_str="";\n' +
        'for (byte i = 0; i < 4; i++) {\n' +
        '  nuid_str += tohex(rfid.uid.uidByte[i]);\n' +
        '}\n' +
        // '// read nuid\n' +
        // 'printHex(rfid.uid.uidByte, rfid.uid.size);\n' +
        // 'Serial.println();\n' +
        '// Halt PICC\n' +
        'rfid.PICC_HaltA();\n' +
        '// Stop encryption on PCD\n' +
        'rfid.PCD_StopCrypto1();\n';
    return code;
}

/* RFID 
 * Read ID
 */
Blockly.Python['RFID_ReadID'] = function(block) {
    var code = "nuid_str";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* GPS 
 * Setup
 */
Blockly.Python["GPS_setup"] = function(block) {
    Blockly.Python.addInclude('GPS_include', "#include <SoftwareSerial.h>\n" +
        "SoftwareSerial gpsSerial(11,10);// MOSI")
    Blockly.Python.addDeclaration("GPS_Dec", "struct\n" +
        "{\n" +
        "  char GPS_Buffer[80];\n" +
        "  bool isGetData;\n" +
        "  bool isParseData;\n" +
        " char UTCTime[11];\n" +
        "  char latitude[11];\n" +
        "  char N_S[2];\n" +
        "  char longitude[12];\n" +
        " char E_W[2];\n" +
        "  bool isUsefull;\n" +
        "} Save_Data;\n" +
        "const unsigned int gpsRxBufferLength = 600;\n" +
        "char gpsRxBuffer[gpsRxBufferLength];\n" +
        "unsigned int ii = 0;\n" +
        "String GPSMODULEstringLat, GPSMODULEstringLong, GPSMODULEgpsLatitude, GPSMODULEgpsLongitude;\n" +
        "float GPSMODULEfloatLat, GPSMODULEfloatLon;\n"
    );
    Blockly.Python.addSetup("GPS_Setup", "gpsSerial.begin(9600);\n" +
        "  Save_Data.isGetData = false;\n" +
        "  Save_Data.isParseData = false;\n" +
        "  Save_Data.isUsefull = false;\n"
    );
    Blockly.Python.addFunction("gpsMoudle", "void gpsModule() {\n" +
        "  gpsRead();\n" + // Get GPS Data
        "  parseGpsBuffer();\n" + // Parse GPS Data
        "  convertRealCoordinate();\n" + // Get real coordinate
        "}\n"
    );
    Blockly.Python.addFunction("convertRealCoordinate", "void convertRealCoordinate() {\n" +
        "   String GPSMODULEstringLat = Save_Data.latitude;\n" +
        "  String GPSMODULEstringLon = Save_Data.longitude;\n" +
        "  float GPSMODULEfloatLat = GPSMODULEstringLat.toFloat();\n" +
        "  float GPSMODULEfloatLon = GPSMODULEstringLon.toFloat();\n" +
        "  GPSMODULEgpsLatitude = String(convertDegMinToDecDeg(GPSMODULEfloatLat), 7);\n" +
        "  GPSMODULEgpsLongitude = String(convertDegMinToDecDeg(GPSMODULEfloatLon), 7);\n" +
        // "  Serial.println(GPSMODULEgpsLatitude);\n"+
        // "  Serial.println(GPSMODULEgpsLongitude);\n"+
        "}\n"
    );
    Blockly.Python.addFunction("convertDegMinToDecDeg", "double convertDegMinToDecDeg (float degMin) {\n" +
        "  double min = 0.0;\n" +
        "  double decDeg = 0.0;\n" +
        "  //get the minutes, fmod() requires double\n" +
        "  min = fmod((double)degMin, 100.0);\n" +
        "  //rebuild coordinates in decimal degrees\n" +
        "  degMin = (int) ( degMin / 100 );\n" +
        "  decDeg = degMin + ( min / 60 );\n" +
        "  return decDeg;\n" +
        "}\n"
    );
    Blockly.Python.addFunction("errorLog", "void errorLog(int num)\n" +
        "{\n" +
        '  Serial.print("ERROR");\n' +
        "  Serial.println(num);\n" +
        "  while (1)\n" +
        "  {\n" +
        "    Serial.flush();\n" +
        "  }\n" +
        "}\n"
    );

    Blockly.Python.addFunction("printGpsBuffer", "void printGpsBuffer()\n" +
        "{\n" +
        " if (Save_Data.isParseData)\n" +
        " {\n" +
        "   Save_Data.isParseData = false;\n" +
        '   Serial.print("Save_Data.UTCTime = ");\n' +
        "   Serial.println(Save_Data.UTCTime);\n" +
        "   if (Save_Data.isUsefull)\n" +
        "   {\n" +
        "     Save_Data.isUsefull = false;\n" +
        '     Serial.print("Save_Data.latitude = ");\n' +
        '     Serial.println(Save_Data.latitude);\n' +
        '     Serial.print("Save_Data.N_S = ");\n' +
        '     Serial.println(Save_Data.N_S);\n' +
        '     Serial.print("Save_Data.longitude = ");\n' +
        '     Serial.println(Save_Data.longitude);\n' +
        '     Serial.print("Save_Data.E_W = ");\n' +
        '     Serial.println(Save_Data.E_W);\n' +
        "   } else {\n" +
        '     Serial.println("GPS DATA is not usefull!");\n' +
        "   }\n" +
        " }\n" +
        "}\n"
    );

    Blockly.Python.addFunction("parseGpsBuffer", "void parseGpsBuffer()\n" +
        "{\n" +
        " char *subString;\n" +
        " char *subStringNext;\n" +
        " if (Save_Data.isGetData)\n" +
        " {\n" +
        "   Save_Data.isGetData = false;\n" +
        '   Serial.println("**************");\n' +
        "   Serial.println(Save_Data.GPS_Buffer);\n" +
        "   for (int i = 0 ; i <= 6 ; i++)\n" +
        "   {\n" +
        "     if (i == 0)\n" +
        "     {\n" +
        "       if ((subString = strstr(Save_Data.GPS_Buffer, \",\")) == NULL)\n" +
        "         errorLog(1);  // Parse error\n" +
        "     }\n" +
        "     else\n" +
        "     {\n" +
        "       subString++;\n" +
        '       if ((subStringNext = strstr(subString, ",")) != NULL)\n' +
        "       {\n" +
        "         char usefullBuffer[2];\n" +
        "         switch (i)\n" +
        "         {\n" +
        "           case 1: memcpy(Save_Data.UTCTime, subString, subStringNext - subString); break;\n" +
        "           case 2: memcpy(usefullBuffer, subString, subStringNext - subString); break;\n" +
        "           case 3: memcpy(Save_Data.latitude, subString, subStringNext - subString); break;\n" +
        "           case 4: memcpy(Save_Data.N_S, subString, subStringNext - subString); break;\n" +
        "           case 5: memcpy(Save_Data.longitude, subString, subStringNext - subString); break;\n" +
        "           case 6: memcpy(Save_Data.E_W, subString, subStringNext - subString); break;\n" +
        "           default: break;\n" +
        "         }\n" +
        "         subString = subStringNext;\n" +
        "         Save_Data.isParseData = true;\n" +
        "         if (usefullBuffer[0] == 'A')\n" +
        "           Save_Data.isUsefull = true;\n" +
        "         else if (usefullBuffer[0] == 'V')\n" +
        "           Save_Data.isUsefull = false;\n" +
        "       }\n" +
        "       else\n" +
        "       {\n" +
        "         errorLog(2);\n" +
        "       }\n" +
        "     }\n" +
        "   }\n" +
        " }\n" +
        "}\n"
    );

    Blockly.Python.addFunction("gpsRead", 'void gpsRead() {\n' +
        '  while (gpsSerial.available())\n' +
        '  {\n' +
        '    gpsRxBuffer[ii++] = gpsSerial.read();\n' +
        '    if (ii == gpsRxBufferLength)clrGpsRxBuffer();\n' +
        '  }\n' +
        '  char* GPS_BufferHead;\n' +
        '  char* GPS_BufferTail;\n' +
        '  if ((GPS_BufferHead = strstr(gpsRxBuffer, "$GPRMC,")) != NULL || (GPS_BufferHead = strstr(gpsRxBuffer, "$GNRMC,")) != NULL )\n' +
        '  {\n' +
        '    if (((GPS_BufferTail = strstr(GPS_BufferHead, "\\r\\n")) != NULL) && (GPS_BufferTail > GPS_BufferHead))\n' +
        '    {\n' +
        '      memcpy(Save_Data.GPS_Buffer, GPS_BufferHead, GPS_BufferTail - GPS_BufferHead);\n' +
        '      Save_Data.isGetData = true;\n' +
        '      clrGpsRxBuffer();\n' +
        '    }\n' +
        '  }\n' +
        '}\n'
    );

    Blockly.Python.addFunction("clrGpsRxBuffer", 'void clrGpsRxBuffer(void) {\n' +
        '  memset(gpsRxBuffer, 0, gpsRxBufferLength);\n' +
        '  ii = 0;\n' +
        '}\n'
    );

    var code = "gpsModule();\n";
    return [code, Blockly.Python.ORDER_ATOMIC];
};

/* GPS 
 * get latitude
 */
Blockly.Python['GPS_getLatitude'] = function(block) {
    var code = "GPSMODULEgpsLatitude";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* GPS 
 * get longitude
 */
Blockly.Python['GPS_getLongitude'] = function(block) {
    var code = "GPSMODULEgpsLongitude";
    return [code, Blockly.Python.ORDER_ATOMIC];
}


/* Water Temperature Sensor, DS18S20
 * setup
 */

Blockly.Python['water_temp_sensor_setup'] = function(block) {
    var dropdown_water_temp_sensor_setup_dropdown = block.getFieldValue('water_temp_sensor_setup_dropdown');
    var number_water_temp_sensor_setup_pin = block.getFieldValue('water_temp_sensor_setup_pin');
    // TODO: Assemble JavaScript into code variable.

    Blockly.Python.addDeclaration("water_temp_sensor_setup_DECLARATION", "#include <OneWire.h>\n" +
        "int DS18S20_Pin = " + number_water_temp_sensor_setup_pin + ";\n" +
        "OneWire ds(DS18S20_Pin);\n"
    );

    Blockly.Python.addFunction("water_temp_sensor_setup_FUNCTION", "float getDS18S20WaterTemp() {\n" +
        "byte data[12];\n" +
        "byte addr[8];\n" +
        "if ( !ds.search(addr)) {\n" +
        "  ds.reset_search();\n" +
        "  return -1000;\n" +
        "}\n" +
        "if ( OneWire::crc8( addr, 7) != addr[7]) {\n" +
        "  Serial.println(\"CRC is not valid!\");\n" +
        "  return -1000;\n" +
        "}\n" +
        "if ( addr[0] != 0x10 && addr[0] != 0x28) {\n" +
        "  Serial.print(\"Device is not recognized\");\n" +
        "  return -1000;\n" +
        "}\n" +
        "ds.reset(); \n" +
        "ds.select(addr); \n" +
        "ds.write(0x44, 1); \n" +
        "byte present = ds.reset(); \n" +
        "ds.select(addr); \n" +
        "ds.write(0xBE); \n" +
        "for (int i = 0; i < 9; i++) { \n" +
        "  data[i] = ds.read(); \n" +
        "} \n" +
        "ds.reset_search();\n" +
        "byte MSB = data[1];\n" +
        "byte LSB = data[0];\n" +
        "float tempRead = ((MSB << 8) | LSB);\n" +
        "float TemperatureSum = tempRead / 16;\n" +
        "return TemperatureSum;\n" +
        "}\n"
    );

    var code = "float getWaterTempValue = getDS18S20WaterTemp();\n"; // no code in loop function here
    return [code, Blockly.Python.ORDER_ATOMIC];
};

/* Water Temperature Sensor, get value
 */

Blockly.Python['water_temp_sensor_get_value'] = function(block) {

    var code = "getWaterTempValue";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

// CO2 sensor setup

Blockly.Python['thirdparty_co2_sensor_setup'] = function(block) {
    var dropdown_thirdparty_co2_sensor_setup_sdapin = block.getFieldValue('thirdparty_co2_sensor_setup_sdapin');
    var dropdown_thirdparty_co2_sensor_setup_sclpin = block.getFieldValue('thirdparty_co2_sensor_setup_sclpin');
    // TODO: Assemble JavaScript into code variable.

    Blockly.Python.addInclude("thirdparty_co2_sensor_setup_include", '#include "Adafruit_CCS811.h"\n');

    Blockly.Python.addDeclaration("thirdparty_co2_sensor_setup_declaration", '' +
        'Adafruit_CCS811 ccs;\n' +
        'uint16_t _ccs811getCO2, _ccs811getTVOC;\n'
    );

    Blockly.Python.addFunction("thirdparty_co2_sensor_setup_function", '' +
        'void _ccs811Setup() {\n' +
        '  Serial.begin(9600);\n' +
        '  Serial.println("CCS811 test");\n' +
        '  if (!ccs.begin()) {\n' +
        '    Serial.println("Failed to start sensor! Please check your wiring.");\n' +
        '    while (1);\n' +
        '  }\n' +
        '  while (!ccs.available());\n' +
        '}\n' +
        '\n' +
        'void _ccs811Main() {\n' +
        '  if (ccs.available()) {\n' +
        '    if (!ccs.readData()) {\n' +
        '      _ccs811getCO2 = ccs.geteCO2();\n' +
        '      _ccs811getTVOC = ccs.getTVOC();\n' +
        '    }\n' +
        '    else {\n' +
        '      Serial.println("ERROR!");\n' +
        '      while (1);\n' +
        '    }\n' +
        '  }\n' +
        '  delay(100);\n' +
        '}\n'
    );

    Blockly.Python.addSetup("thirdparty_co2_sensor_setup_setup", '_ccs811Setup();\n');

    var code = "_ccs811Main();\n"; // no code in loop function here

    return [code, Blockly.Python.ORDER_ATOMIC];
};


/* CO2 sensor get Co2
 */

Blockly.Python['thirdparty_co2_sensor_get_co2'] = function(block) {

    var code = "_ccs811getCO2";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

/* CO2 sensor get TVOC
 */

Blockly.Python['thirdparty_co2_sensor_get_tvoc'] = function(block) {

    var code = "_ccs811getTVOC";
    return [code, Blockly.Python.ORDER_ATOMIC];
}

// nrf module

/* 

Blockly.Python.addInclude("", ''+

'');

Blockly.Python.addDeclaration("", ''+

'');

Blockly.Python.addSetup("", ''+

'');

Blockly.Python.addFunction("", ''+

'');

*/

Blockly.Python['thirdparty_nrf24l01_setup'] = function(block) {
    var dropdown_thirdparty_nrf24l01_setup_dropdown_cepin = block.getFieldValue('thirdparty_nrf24l01_setup_dropdown_cepin');
    var dropdown_thirdparty_nrf24l01_setup_dropdown_csnpin = block.getFieldValue('thirdparty_nrf24l01_setup_dropdown_csnpin');
    var text_thirdparty_nrf24l01_setup_addr = block.getFieldValue('thirdparty_nrf24l01_setup_addr');
    // TODO: Assemble JavaScript into code variable.

    Blockly.Python.addInclude("thirdparty_nrf24l01_setup_include", '' +
        '#include <SPI.h>\n' +
        '#include <nRF24L01.h>\n' +
        '#include <RF24.h>)\n' +
        '');

    Blockly.Python.addDeclaration("thirdparty_nrf24l01_setup_declaration", '' +
        'RF24 radio(7, 5);\n' +
        'const byte address[6] = "' + text_thirdparty_nrf24l01_setup_addr + '";\n' +
        '');

    Blockly.Python.addSetup("thirdparty_nrf24l01_setup_setup", '' +
        'radio.begin();\n' +
        '');

    var code = '';
    return code;
};

Blockly.Python['thirdparty_nrf24l01_send_data'] = function(block) {
    var text_thirdparty_nrf24l01_send_data_data = block.getFieldValue('thirdparty_nrf24l01_send_data_data');
    // TODO: Assemble JavaScript into code variable.

    Blockly.Python.addSetup("thirdparty_nrf24l01_send_data_setup", '' +
        'radio.openWritingPipe(address);\n' +
        'radio.setPALevel(RF24_PA_MIN);\n' +
        'radio.stopListening();\n' +
        '');

    var code = '' +
        'const char text[] = "' + text_thirdparty_nrf24l01_send_data_data + '";\n' +
        'radio.write(&text, sizeof(text));\n' +
        '';
    return code;
};

Blockly.Python['thirdparty_nrf24l01_receive_data'] = function(block) {
    // TODO: Assemble JavaScript into code variable.

    Blockly.Python.addDeclaration("thirdparty_nrf24l01_receive_data_declare", '' +
        'char _nrfText[32] = "";\n' +
        '')

    Blockly.Python.addSetup("thirdparty_nrf24l01_receive_data_setup", '' +
        'radio.openReadingPipe(0, address);\n' +
        'radio.setPALevel(RF24_PA_MIN);\n' +
        'radio.startListening();\n' +
        '');

    Blockly.Python.addFunction("thirdparty_nrf24l01_receive_data_function", '' +
        'void _nrfReceiveDataSet() {\n' +
        '  if (radio.available()) {\n' +
        '    radio.read(&_nrfText, sizeof(_nrfText));\n' +
        '  }\n' +
        '}\n' +
        '');

    var code = '_nrfReceiveDataSet();\n';
    return code;
};

Blockly.Python['thirdparty_nrf24l01_data_received'] = function(block) {
    // TODO: Assemble JavaScript into code variable.
    var code = '_nrfText';
    // TODO: Change ORDER_NONE to the correct strength.
    return [code, Blockly.Python.ORDER_ATOMIC];
};