Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
EdOliver
Published © MIT

Health and Fitness Tracker

Two wearable devices that become a fitness tracker using the NXP Rapid IoT prototyping kit, ESP8266 board and AWS. Alexa compatible!

AdvancedFull instructions provided20 hours1,895

Things used in this project

Story

Read more

Custom parts and enclosures

Case CAD files

These work just fine whether you cut Acrylic or wood. Just grab a drill and try not to miss on the holes.

Schematics

System Architecture

From the two wearables you upload everything to dynamoDB basically and then you can play with lambdas to reach anything you wish to reach.

Code

Fitness tracker ATMO file

JSON
Just go to NXP Atmosphere's IDE and load it. You still have to input your values for IAM role and DB database.
To the Amazon Overlords: please good sirs, of course I erased the credentials.
{
  "name": "FitnessTracker",
  "createVersion": "2017-08-12",
  "description": "Temperature and steps for the NXP's Rapid IoT Prototyping kit's contest.\nIt uploads those two variables to a Dynamo DB database.",
  "lastModified": "2019-02-05T09:28:49.153Z",
  "created": "2019-02-05T09:28:49.153Z",
  "meta": {
    "projectTypeName": "NXP Rapid IoT",
    "projectTypeId": "NxpRpk"
  },
  "planes": {
    "NXP Rapid IoT": {
      "type": "mcuxpresso",
      "compilerVersion": "latest",
      "variants": [
        "NxpRpk"
      ],
      "meta": {},
      "elements": [
        {
          "name": "Interval",
          "type": "EmbeddedInterval",
          "variants": [
            "embedded",
            "triggers",
            "abilities",
            "properties",
            "variables"
          ],
          "properties": {
            "errorData": {},
            "code": {
              "trigger": "\treturn ATMO_Status_Success;",
              "setup": "\n\tATMO_INTERVAL_Handle_t intervalHandle;\n    ATMO_INTERVAL_AddAbilityInterval(\n\t\tATMO_PROPERTY(Interval, instance), \n\t\tATMO_ABILITY(Interval, interval), \n\t\tATMO_PROPERTY(Interval, time), \n\t\t&intervalHandle\n\t);\n\t\n\treturn ATMO_Status_Success;\n\t",
              "interval": "\treturn ATMO_Status_Success;"
            },
            "variables": {},
            "embeddedPropertyConversions": {},
            "codeUserChanged": {
              "setup": false,
              "interval": false
            },
            "instance": "ATMO_DRIVERINSTANCE_INTERVAL_INTERVAL1",
            "time": "3000"
          },
          "meta": {
            "editorX": 90,
            "editorY": 227,
            "lastTrigger": "interval"
          },
          "triggers": {
            "triggered": [],
            "interval": [
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "ENS210TemperatureHumidity",
                "targetAbility": "readTemperature"
              }
            ]
          },
          "interruptAbilities": {
            "trigger": false,
            "setup": false,
            "interval": true
          },
          "abilities": [
            {
              "name": "trigger",
              "triggers": [
                "triggered"
              ]
            },
            {
              "name": "setup",
              "triggers": []
            },
            {
              "name": "interval",
              "triggers": [
                "interval"
              ]
            }
          ]
        },
        {
          "name": "BLECharacteristicCustom",
          "type": "EmbeddedBLECharacteristicCustom",
          "variants": [
            "embedded",
            "triggers",
            "abilities",
            "properties",
            "variables",
            "ble"
          ],
          "properties": {
            "errorData": {},
            "code": {
              "trigger": "\treturn ATMO_Status_Success;",
              "setup": "\n\tATMO_BLE_GATTSAddService(\n\t\tATMO_PROPERTY(BLECharacteristicCustom, instance),\n\t\t&ATMO_VARIABLE(BLECharacteristicCustom, bleServiceHandle), \n\t\tATMO_PROPERTY(BLECharacteristicCustom, bleServiceUuid));\n\t\n\tuint8_t property = 0;\n\tuint8_t permission = 0;\n\t\n\tproperty |= ATMO_PROPERTY(BLECharacteristicCustom, read) ? ATMO_BLE_Property_Read : 0;\n\tproperty |= ATMO_PROPERTY(BLECharacteristicCustom, write) ? ATMO_BLE_Property_Write : 0;\n\tproperty |= ATMO_PROPERTY(BLECharacteristicCustom, notify) ? ATMO_BLE_Property_Notify : 0;\n\n\tpermission |= ATMO_PROPERTY(BLECharacteristicCustom, read) ? ATMO_BLE_Permission_Read : 0;\n\tpermission |= ATMO_PROPERTY(BLECharacteristicCustom, write) ? ATMO_BLE_Permission_Write : 0;\n\n\tATMO_DATATYPE types[3] = {ATMO_PROPERTY(BLECharacteristicCustom, writeDataType), ATMO_PROPERTY(BLECharacteristicCustom, readDataType), ATMO_PROPERTY(BLECharacteristicCustom, notifyDataType)};\n\t\n\tATMO_BLE_GATTSAddCharacteristic(\n\t\tATMO_PROPERTY(BLECharacteristicCustom, instance),\n\t\t&ATMO_VARIABLE(BLECharacteristicCustom, bleCharacteristicHandle), \n\t\tATMO_VARIABLE(BLECharacteristicCustom, bleServiceHandle), \n\t\tATMO_PROPERTY(BLECharacteristicCustom, bleCharacteristicUuid), \n\t\tproperty, permission, ATMO_GetMaxValueSize(3, 64, types));\n\t\n\tATMO_BLE_GATTSRegisterCharacteristicAbilityHandle(\n\t\tATMO_PROPERTY(BLECharacteristicCustom, instance),\n\t\tATMO_VARIABLE(BLECharacteristicCustom, bleCharacteristicHandle), \n\t\tATMO_BLE_Characteristic_Written, \n\t\tATMO_ABILITY(BLECharacteristicCustom, written));\n\t\n\treturn ATMO_Status_Success;\n\t",
              "setValue": "\n\t\n\t// Convert to the desired write data type\n\tATMO_Value_t convertedValue;\n\tATMO_InitValue(&convertedValue);\n\tATMO_CreateValueConverted(&convertedValue, ATMO_PROPERTY(BLECharacteristicCustom, readDataType), in);\n\n\tATMO_BLE_GATTSSetCharacteristic(\n\t\tATMO_PROPERTY(BLECharacteristicCustom, instance),\n\t\tATMO_VARIABLE(BLECharacteristicCustom, bleCharacteristicHandle),\n\t\tconvertedValue.size, \n\t\t(uint8_t *)convertedValue.data,\n\t\tNULL);\n\t\n\tATMO_FreeValue(&convertedValue);\n\t\t\n\treturn ATMO_Status_Success;\n\t",
              "written": "\n\tATMO_CreateValueConverted(out, ATMO_PROPERTY(BLECharacteristicCustom, writeDataType), in);\n\treturn ATMO_Status_Success;\n\t",
              "subscibed": "\treturn ATMO_Status_Success;",
              "unsubscribed": "\treturn ATMO_Status_Success;"
            },
            "variables": {
              "bleServiceHandle": {
                "type": "ATMO_BLE_Handle_t"
              },
              "bleCharacteristicHandle": {
                "type": "ATMO_BLE_Handle_t"
              }
            },
            "embeddedPropertyConversions": {
              "bleServiceUuid": "string",
              "bleCharacteristicUuid": "string"
            },
            "codeUserChanged": {
              "setup": false,
              "setValue": false,
              "written": false,
              "subscibed": false,
              "unsubscribed": false
            },
            "instance": "ATMO_DRIVERINSTANCE_BLE_BLE1",
            "bleServiceUuid": "5baa833b-89a5-41d1-a3b2-20a39216aa52",
            "bleCharacteristicUuid": "5baa833b-89a5-41d1-a3b2-20a39216aa53",
            "read": true,
            "write": true,
            "notify": false,
            "readDataType": "ATMO_DATATYPE_FLOAT",
            "writeDataType": "ATMO_DATATYPE_FLOAT",
            "notifyDataType": "ATMO_DATATYPE_FLOAT"
          },
          "meta": {
            "editorX": 518,
            "editorY": 78,
            "lastTrigger": "written"
          },
          "triggers": {
            "triggered": [],
            "written": [],
            "subscibed": [],
            "unsubscribed": []
          },
          "interruptAbilities": {
            "trigger": false,
            "setup": false,
            "setValue": "valueSet",
            "written": true,
            "subscibed": true,
            "unsubscribed": true
          },
          "abilities": [
            {
              "name": "trigger",
              "triggers": [
                "triggered"
              ]
            },
            {
              "name": "setup",
              "triggers": []
            },
            {
              "name": "setValue",
              "triggers": []
            },
            {
              "name": "written",
              "triggers": [
                "written"
              ]
            },
            {
              "name": "subscibed",
              "triggers": [
                "subscibed"
              ]
            },
            {
              "name": "unsubscribed",
              "triggers": [
                "unsubscribed"
              ]
            }
          ]
        },
        {
          "name": "ENS210TemperatureHumidity",
          "type": "EmbeddedENS210",
          "variants": [
            "embedded",
            "triggers",
            "abilities",
            "properties",
            "variables"
          ],
          "properties": {
            "errorData": {},
            "code": {
              "trigger": "\treturn ATMO_Status_Success;",
              "setup": "\tATMO_ENS210_Config_t config;\n\tconfig.address = ATMO_PROPERTY(ENS210TemperatureHumidity, i2cAddress);\n\tconfig.i2cDriverInstance = ATMO_PROPERTY(ENS210TemperatureHumidity, i2cInstance);\n\tconfig.tempCalibrationOffset = ATMO_PROPERTY(ENS210TemperatureHumidity, tempCalibrationOffset);\n\n\treturn ( ATMO_ENS210_Init(&config) == ATMO_ENS210_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;\n",
              "setEnabled": "ATMO_ENS210_SetEnabled(true);\nreturn ATMO_Status_Success;",
              "setDisabled": "ATMO_ENS210_SetEnabled(false);\nreturn ATMO_Status_Success;",
              "setEnabledDisabled": "bool enabled = false;\nATMO_GetBool(in, &enabled);\nATMO_ENS210_SetEnabled(enabled);\nreturn ATMO_Status_Success;",
              "readTemperature": "    float tempC;\n    \n    if(ATMO_ENS210_GetTemperatureFloat(&tempC) == ATMO_ENS210_Status_Success)\n    {\n        ATMO_CreateValueFloat(out, tempC);\n    }\n    else\n    {\n        ATMO_CreateValueVoid(out);\n    }\n    \n    return ATMO_Status_Success;",
              "readHumidity": "    float humidityPct;\n\n    if(ATMO_ENS210_GetHumidityFloat(&humidityPct) == ATMO_ENS210_Status_Success)\n    {\n        ATMO_CreateValueFloat(out, humidityPct);\n    }\n    else\n    {\n        ATMO_CreateValueVoid(out);\n    }\n    \n    return ATMO_Status_Success;"
            },
            "variables": {},
            "embeddedPropertyConversions": {},
            "codeUserChanged": {
              "setup": false,
              "setEnabled": false,
              "setDisabled": false,
              "setEnabledDisabled": false,
              "readTemperature": false,
              "readHumidity": false
            },
            "i2cInstance": "ATMO_DRIVERINSTANCE_I2C_I2C2",
            "i2cAddress": "0x43",
            "tempCalibrationOffset": -7
          },
          "meta": {
            "editorX": 205,
            "editorY": 233,
            "lastTrigger": "temperatureRead"
          },
          "triggers": {
            "triggered": [],
            "temperatureRead": [
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "Function",
                "targetAbility": "trigger"
              },
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "BLECharacteristicCustom1",
                "targetAbility": "setValue"
              }
            ],
            "humidityRead": []
          },
          "interruptAbilities": {
            "trigger": false,
            "setup": false,
            "setEnabled": false,
            "setDisabled": false,
            "setEnabledDisabled": false,
            "readTemperature": false,
            "readHumidity": false
          },
          "abilities": [
            {
              "name": "trigger",
              "triggers": [
                "triggered"
              ]
            },
            {
              "name": "setup",
              "triggers": []
            },
            {
              "name": "setEnabled",
              "triggers": []
            },
            {
              "name": "setDisabled",
              "triggers": []
            },
            {
              "name": "setEnabledDisabled",
              "triggers": []
            },
            {
              "name": "readTemperature",
              "triggers": [
                "temperatureRead"
              ]
            },
            {
              "name": "readHumidity",
              "triggers": [
                "humidityRead"
              ]
            }
          ]
        },
        {
          "name": "EmbeddedIconLabelDisplay1",
          "type": "EmbeddedIconLabelDisplay",
          "variants": [
            "embedded",
            "triggers",
            "abilities",
            "properties",
            "variables",
            "rpk"
          ],
          "properties": {
            "errorData": {},
            "code": {
              "trigger": "\treturn ATMO_Status_Success;",
              "displayPage": "\n\tATMO_UI_Page_DisplayPageByCoord(ATMO_PROPERTY(EmbeddedIconLabelDisplay1, x), ATMO_PROPERTY(EmbeddedIconLabelDisplay1, y), false);\n\treturn ATMO_Status_Success;\n\t",
              "onDisplayed": "\n\treturn ATMO_Status_Success;\n    ",
              "topRightButtonPressed": "\n\treturn ATMO_Status_Success;\n\t",
              "bottomRightButtonPressed": "\n\treturn ATMO_Status_Success;\n\t",
              "topLeftButtonPressed": "\n\treturn ATMO_Status_Success;\n\t",
              "bottomLeftButtonPressed": "\n\treturn ATMO_Status_Success;\n\t",
              "setup": "\n    ATMO_UI_PAGE_Config_t config;\n\tconfig.hidden = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, pageHidden);\n\tconfig.textColor = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, textColor);\n    config.activeButtons = ATMO_UI_Page_GetButtonMask(ATMO_PROPERTY(EmbeddedIconLabelDisplay1, topRightButtonEnabled),\n    ATMO_PROPERTY(EmbeddedIconLabelDisplay1,bottomRightButtonEnabled), ATMO_PROPERTY(EmbeddedIconLabelDisplay1, topLeftButtonEnabled), ATMO_PROPERTY(EmbeddedIconLabelDisplay1, bottomLeftButtonEnabled));\n\tconfig.x = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, x);\n    config.x = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, x);\n    config.y = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, y);\n\tstrncpy(config.topLeftButtonLabel, ATMO_PROPERTY(EmbeddedIconLabelDisplay1, topLeftButtonLabel), ATMO_BUTTON_LABEL_MAXLEN);\n\tstrncpy(config.topRightButtonLabel, ATMO_PROPERTY(EmbeddedIconLabelDisplay1, topRightButtonLabel), ATMO_BUTTON_LABEL_MAXLEN);\n\tstrncpy(config.bottomLeftButtonLabel, ATMO_PROPERTY(EmbeddedIconLabelDisplay1, bottomLeftButtonLabel), ATMO_BUTTON_LABEL_MAXLEN);\n\tstrncpy(config.bottomRightButtonLabel, ATMO_PROPERTY(EmbeddedIconLabelDisplay1, bottomRightButtonLabel), ATMO_BUTTON_LABEL_MAXLEN);\n    config.spanX = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, spanX);\n\tconfig.spanY = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, spanY);\n    config.title = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, pageTitle);\n    config.titleHidden = ATMO_PROPERTY(EmbeddedIconLabelDisplay1, titleHidden);\n\tATMO_UI_SINGLEICONTEXT_Init(&config);\n\tATMO_VARIABLE(EmbeddedIconLabelDisplay1, pageHandle) = config.templateInstance;\n    ATMO_UI_SINGLEICONTEXT_SetMainText(config.templateInstance, ATMO_PROPERTY(EmbeddedIconLabelDisplay1, label));\n    ATMO_UI_SINGLEICONTEXT_SetIcon(config.templateInstance, ATMO_PROPERTY(EmbeddedIconLabelDisplay1, icon));\n    ATMO_UI_SINGLEICONTEXT_RegisterOnDisplayedAbilityHandle(ATMO_VARIABLE(EmbeddedIconLabelDisplay1,pageHandle), ATMO_ABILITY(EmbeddedIconLabelDisplay1, onDisplayed));\n    ATMO_UI_SINGLEICONTEXT_RegisterButtonAbilityHandle(ATMO_VARIABLE(EmbeddedIconLabelDisplay1,pageHandle), 1, ATMO_ABILITY(EmbeddedIconLabelDisplay1, topRightButtonPressed));\n\tATMO_UI_SINGLEICONTEXT_RegisterButtonAbilityHandle(ATMO_VARIABLE(EmbeddedIconLabelDisplay1,pageHandle), 2, ATMO_ABILITY(EmbeddedIconLabelDisplay1, bottomRightButtonPressed));\n\tATMO_UI_SINGLEICONTEXT_RegisterButtonAbilityHandle(ATMO_VARIABLE(EmbeddedIconLabelDisplay1,pageHandle), 3, ATMO_ABILITY(EmbeddedIconLabelDisplay1, topLeftButtonPressed));\n    ATMO_UI_SINGLEICONTEXT_RegisterButtonAbilityHandle(ATMO_VARIABLE(EmbeddedIconLabelDisplay1,pageHandle), 4, ATMO_ABILITY(EmbeddedIconLabelDisplay1, bottomLeftButtonPressed));\n    ATMO_UI_SINGLEICONTEXT_RegisterOnLeaveAbilityHandle(config.templateInstance, ATMO_ABILITY(EmbeddedIconLabelDisplay1, onLeave));\n\treturn ATMO_Status_Success;\n    ",
              "onLeave": "\n\treturn ATMO_Status_Success;\n\t",
              "setLabel": "\n    char label[32];\n    if(ATMO_GetString(in, label, 32) == ATMO_Status_Success)\n    {\n        ATMO_UI_SINGLEICONTEXT_SetMainText(ATMO_VARIABLE(EmbeddedIconLabelDisplay1,pageHandle), label);\n    }\n    else\n    {\n        return ATMO_Status_Fail;\n    }\n\n    return ATMO_Status_Success;\n    "
            },
            "variables": {
              "pageHandle": {
                "type": "ATMO_DriverInstanceHandle_t"
              }
            },
            "embeddedPropertyConversions": {
              "pageTitle": "string",
              "topRightButtonLabel": "string",
              "bottomRightButtonLabel": "string",
              "topLeftButtonLabel": "string",
              "bottomLeftButtonLabel": "string",
              "label": "string"
            },
            "codeUserChanged": {
              "displayPage": false,
              "onDisplayed": false,
              "topRightButtonPressed": false,
              "bottomRightButtonPressed": false,
              "topLeftButtonPressed": false,
              "bottomLeftButtonPressed": false,
              "setup": false,
              "onLeave": false,
              "setLabel": false
            },
            "textColor": "GUI_BLACK",
            "pageTitle": "Temperature",
            "titleHidden": false,
            "pageHidden": false,
            "topRightButtonLabel": "",
            "topRightButtonEnabled": false,
            "bottomRightButtonLabel": "",
            "bottomRightButtonEnabled": false,
            "topLeftButtonLabel": "",
            "topLeftButtonEnabled": false,
            "bottomLeftButtonLabel": "",
            "bottomLeftButtonEnabled": false,
            "x": 0,
            "y": "-1",
            "spanX": 1,
            "spanY": 1,
            "icon": "icon_applications_thermostat",
            "label": ""
          },
          "meta": {
            "editorX": 495,
            "editorY": 191,
            "lastTrigger": "onDisplayed"
          },
          "triggers": {
            "triggered": [],
            "onDisplayed": [],
            "topRightButtonPressed": [],
            "bottomRightButtonPressed": [],
            "topLeftButtonPressed": [],
            "bottomLeftButtonPressed": [],
            "onLeave": []
          },
          "interruptAbilities": {
            "trigger": false,
            "displayPage": false,
            "onDisplayed": false,
            "topRightButtonPressed": false,
            "bottomRightButtonPressed": false,
            "topLeftButtonPressed": false,
            "bottomLeftButtonPressed": false,
            "setup": false,
            "onLeave": false,
            "setLabel": false
          },
          "abilities": [
            {
              "name": "trigger",
              "triggers": [
                "triggered"
              ]
            },
            {
              "name": "displayPage",
              "triggers": []
            },
            {
              "name": "onDisplayed",
              "triggers": [
                "onDisplayed"
              ]
            },
            {
              "name": "topRightButtonPressed",
              "triggers": [
                "topRightButtonPressed"
              ]
            },
            {
              "name": "bottomRightButtonPressed",
              "triggers": [
                "bottomRightButtonPressed"
              ]
            },
            {
              "name": "topLeftButtonPressed",
              "triggers": [
                "topLeftButtonPressed"
              ]
            },
            {
              "name": "bottomLeftButtonPressed",
              "triggers": [
                "bottomLeftButtonPressed"
              ]
            },
            {
              "name": "setup",
              "triggers": []
            },
            {
              "name": "onLeave",
              "triggers": [
                "onLeave"
              ]
            },
            {
              "name": "setLabel",
              "triggers": []
            }
          ]
        },
        {
          "name": "BLECharacteristicCustom1",
          "type": "EmbeddedBLECharacteristicCustom",
          "variants": [
            "embedded",
            "triggers",
            "abilities",
            "properties",
            "variables",
            "ble"
          ],
          "properties": {
            "errorData": {},
            "code": {
              "trigger": "\treturn ATMO_Status_Success;",
              "setup": "\n\tATMO_BLE_GATTSAddService(\n\t\tATMO_PROPERTY(BLECharacteristicCustom1, instance),\n\t\t&ATMO_VARIABLE(BLECharacteristicCustom1, bleServiceHandle), \n\t\tATMO_PROPERTY(BLECharacteristicCustom1, bleServiceUuid));\n\t\n\tuint8_t property = 0;\n\tuint8_t permission = 0;\n\t\n\tproperty |= ATMO_PROPERTY(BLECharacteristicCustom1, read) ? ATMO_BLE_Property_Read : 0;\n\tproperty |= ATMO_PROPERTY(BLECharacteristicCustom1, write) ? ATMO_BLE_Property_Write : 0;\n\tproperty |= ATMO_PROPERTY(BLECharacteristicCustom1, notify) ? ATMO_BLE_Property_Notify : 0;\n\n\tpermission |= ATMO_PROPERTY(BLECharacteristicCustom1, read) ? ATMO_BLE_Permission_Read : 0;\n\tpermission |= ATMO_PROPERTY(BLECharacteristicCustom1, write) ? ATMO_BLE_Permission_Write : 0;\n\n\tATMO_DATATYPE types[3] = {ATMO_PROPERTY(BLECharacteristicCustom1, writeDataType), ATMO_PROPERTY(BLECharacteristicCustom1, readDataType), ATMO_PROPERTY(BLECharacteristicCustom1, notifyDataType)};\n\t\n\tATMO_BLE_GATTSAddCharacteristic(\n\t\tATMO_PROPERTY(BLECharacteristicCustom1, instance),\n\t\t&ATMO_VARIABLE(BLECharacteristicCustom1, bleCharacteristicHandle), \n\t\tATMO_VARIABLE(BLECharacteristicCustom1, bleServiceHandle), \n\t\tATMO_PROPERTY(BLECharacteristicCustom1, bleCharacteristicUuid), \n\t\tproperty, permission, ATMO_GetMaxValueSize(3, 64, types));\n\t\n\tATMO_BLE_GATTSRegisterCharacteristicAbilityHandle(\n\t\tATMO_PROPERTY(BLECharacteristicCustom1, instance),\n\t\tATMO_VARIABLE(BLECharacteristicCustom1, bleCharacteristicHandle), \n\t\tATMO_BLE_Characteristic_Written, \n\t\tATMO_ABILITY(BLECharacteristicCustom1, written));\n\t\n\treturn ATMO_Status_Success;\n\t",
              "setValue": "\n\t\n\t// Convert to the desired write data type\n\tATMO_Value_t convertedValue;\n\tATMO_InitValue(&convertedValue);\n\tATMO_CreateValueConverted(&convertedValue, ATMO_PROPERTY(BLECharacteristicCustom1, readDataType), in);\n\n\tATMO_BLE_GATTSSetCharacteristic(\n\t\tATMO_PROPERTY(BLECharacteristicCustom1, instance),\n\t\tATMO_VARIABLE(BLECharacteristicCustom1, bleCharacteristicHandle),\n\t\tconvertedValue.size, \n\t\t(uint8_t *)convertedValue.data,\n\t\tNULL);\n\t\n\tATMO_FreeValue(&convertedValue);\n\t\t\n\treturn ATMO_Status_Success;\n\t",
              "written": "\n\tATMO_CreateValueConverted(out, ATMO_PROPERTY(BLECharacteristicCustom1, writeDataType), in);\n\treturn ATMO_Status_Success;\n\t",
              "subscibed": "\treturn ATMO_Status_Success;",
              "unsubscribed": "\treturn ATMO_Status_Success;"
            },
            "variables": {
              "bleServiceHandle": {
                "type": "ATMO_BLE_Handle_t"
              },
              "bleCharacteristicHandle": {
                "type": "ATMO_BLE_Handle_t"
              }
            },
            "embeddedPropertyConversions": {
              "bleServiceUuid": "string",
              "bleCharacteristicUuid": "string"
            },
            "codeUserChanged": {
              "setup": false,
              "setValue": false,
              "written": false,
              "subscibed": false,
              "unsubscribed": false
            },
            "instance": "ATMO_DRIVERINSTANCE_BLE_BLE1",
            "bleServiceUuid": "5baa833b-89a5-41d1-a3b2-20a39216aa52",
            "bleCharacteristicUuid": "5baa833b-89a5-41d1-a3b2-20a39216aa54",
            "read": true,
            "write": true,
            "notify": false,
            "readDataType": "ATMO_DATATYPE_FLOAT",
            "writeDataType": "ATMO_DATATYPE_FLOAT",
            "notifyDataType": "ATMO_DATATYPE_FLOAT"
          },
          "meta": {
            "editorX": 454,
            "editorY": 276,
            "lastTrigger": "written"
          },
          "triggers": {
            "triggered": [],
            "written": [],
            "subscibed": [],
            "unsubscribed": []
          },
          "interruptAbilities": {
            "trigger": false,
            "setup": false,
            "setValue": "valueSet",
            "written": true,
            "subscibed": true,
            "unsubscribed": true
          },
          "abilities": [
            {
              "name": "trigger",
              "triggers": [
                "triggered"
              ]
            },
            {
              "name": "setup",
              "triggers": []
            },
            {
              "name": "setValue",
              "triggers": []
            },
            {
              "name": "written",
              "triggers": [
                "written"
              ]
            },
            {
              "name": "subscibed",
              "triggers": [
                "subscibed"
              ]
            },
            {
              "name": "unsubscribed",
              "triggers": [
                "unsubscribed"
              ]
            }
          ]
        },
        {
          "name": "FXOS8700AccelerometerMagnetometer",
          "type": "EmbeddedFXOS8700",
          "variants": [
            "embedded",
            "triggers",
            "abilities",
            "properties",
            "variables"
          ],
          "properties": {
            "errorData": {},
            "code": {
              "trigger": "\treturn ATMO_Status_Success;",
              "setup": "\tATMO_FXOS8700_Config_t config;\n\tconfig.address = ATMO_PROPERTY(FXOS8700AccelerometerMagnetometer, i2cAddress);\n\tconfig.i2cDriverInstance = ATMO_PROPERTY(FXOS8700AccelerometerMagnetometer, i2cInstance);\n\tconfig.gpioDriverInstance = ATMO_PROPERTY(FXOS8700AccelerometerMagnetometer, gpioInstance);\n\tconfig.int1En = ATMO_PROPERTY(FXOS8700AccelerometerMagnetometer, interrupt1Enabled);\n    config.int2En = ATMO_PROPERTY(FXOS8700AccelerometerMagnetometer, interrupt2Enabled);\n    config.int1Pin = ATMO_PROPERTY(FXOS8700AccelerometerMagnetometer, interrupt1Gpio);\n    config.int2Pin = ATMO_PROPERTY(FXOS8700AccelerometerMagnetometer, interrupt2Gpio);\n\n    switch(ATMO_PROPERTY(FXOS8700AccelerometerMagnetometer, motionDetectType))\n    {\n        case FXOS8700_NoDetect:\n        {\n            config.freefallEnabled = false;\n            config.motionEnabled = false;\n            config.tapDetectionEnabled = false;\n            break;\n        }\n        case FXOS8700_FreefallDetect:\n        {\n            config.freefallEnabled = true;\n            config.motionEnabled = false;\n            config.tapDetectionEnabled = false;\n            break;\n        }\n        case FXOS8700_MotionDetect:\n        {\n            config.freefallEnabled = false;\n            config.motionEnabled = true;\n            config.tapDetectionEnabled = false;\n            break;\n        }\n        case FXOS8700_TapDetect:\n        {\n            config.freefallEnabled = false;\n            config.motionEnabled = false;\n            config.tapDetectionEnabled = true;\n            break; \n        }\n        default:\n        {\n            config.freefallEnabled = false;\n            config.motionEnabled = false;  \n            config.tapDetectionEnabled = false;\n            break;\n        }\n    }\n\n    ATMO_FXOS8700_SetMotionDetectedAbilityHandle(ATMO_ABILITY(FXOS8700AccelerometerMagnetometer, detectMotion));\n    ATMO_FXOS8700_SetFreefallDetectedAbilityHandle(ATMO_ABILITY(FXOS8700AccelerometerMagnetometer, detectFreefall));\n    ATMO_FXOS8700_SetTapDetectedAbilityHandle(ATMO_ABILITY(FXOS8700AccelerometerMagnetometer, detectTap));\n\tATMO_FXOS8700_Init(&config);\n\n    return ATMO_Status_Success;\n\t",
              "setEnabled": "ATMO_FXOS8700_SetEnabled(true);\nreturn ATMO_Status_Success;",
              "setDisabled": "ATMO_FXOS8700_SetEnabled(false);\nreturn ATMO_Status_Success;",
              "setEnabledDisabled": "bool enabled = false;\nATMO_GetBool(in, &enabled);\nATMO_FXOS8700_SetEnabled(enabled);\nreturn ATMO_Status_Success;",
              "getAccelData": "    ATMO_3dFloatVector_t data;\r\n\r\n    if( ATMO_FXOS8700_GetAccelData(&data) != ATMO_FXOS8700_Status_Success )\r\n    {\r\n        ATMO_CreateValueVoid(out);\r\n        return ATMO_Status_Fail;\r\n    }\r\n\r\n    ATMO_CreateValue3dVectorFloat(out, &data);\r\n\r\n    return ATMO_Status_Success;",
              "getAccelX": "\tATMO_3dFloatVector_t data;\n\n\tif(ATMO_FXOS8700_GetAccelData(&data) != ATMO_FXOS8700_Status_Success)\n\t{\n\t\tATMO_CreateValueVoid(out);\n\t\treturn ATMO_Status_Fail;\n\t}\n\n\tATMO_CreateValueFloat(out, data.x);\n\treturn ATMO_Status_Success;\n",
              "getAccelY": "\tATMO_3dFloatVector_t data;\n\n\tif(ATMO_FXOS8700_GetAccelData(&data) != ATMO_FXOS8700_Status_Success)\n\t{\n\t\tATMO_CreateValueVoid(out);\n\t\treturn ATMO_Status_Fail;\n\t}\n\n\tATMO_CreateValueFloat(out, data.y);\n\treturn ATMO_Status_Success;\n",
              "getAccelZ": "\tATMO_3dFloatVector_t data;\n\n\tif(ATMO_FXOS8700_GetAccelData(&data) != ATMO_FXOS8700_Status_Success)\n\t{\n\t\tATMO_CreateValueVoid(out);\n\t\treturn ATMO_Status_Fail;\n\t}\n\n\tATMO_CreateValueFloat(out, data.z);\n\treturn ATMO_Status_Success;\n",
              "getMagData": "    ATMO_3dFloatVector_t data;\r\n\r\n    if( ATMO_FXOS8700_GetMagData(&data) != ATMO_FXOS8700_Status_Success )\r\n    {\r\n        ATMO_CreateValueVoid(out);\r\n        return ATMO_Status_Fail;\r\n    }\r\n\r\n    ATMO_CreateValue3dVectorFloat(out, &data);\r\n\r\n    return ATMO_Status_Success;",
              "getMagX": "\tATMO_3dFloatVector_t data;\n\n\tif(ATMO_FXOS8700_GetMagData(&data) != ATMO_FXOS8700_Status_Success)\n\t{\n\t\tATMO_CreateValueVoid(out);\n\t\treturn ATMO_Status_Fail;\n\t}\n\n\tATMO_CreateValueFloat(out, data.x);\n\treturn ATMO_Status_Success;\n",
              "getMagY": "\tATMO_3dFloatVector_t data;\n\n\tif(ATMO_FXOS8700_GetMagData(&data) != ATMO_FXOS8700_Status_Success)\n\t{\n\t\tATMO_CreateValueVoid(out);\n\t\treturn ATMO_Status_Fail;\n\t}\n\n\tATMO_CreateValueFloat(out, data.y);\n\treturn ATMO_Status_Success;\n",
              "getMagZ": "\tATMO_3dFloatVector_t data;\n\n\tif(ATMO_FXOS8700_GetMagData(&data) != ATMO_FXOS8700_Status_Success)\n\t{\n\t\tATMO_CreateValueVoid(out);\n\t\treturn ATMO_Status_Fail;\n\t}\n\n\tATMO_CreateValueFloat(out, data.z);\n\treturn ATMO_Status_Success;\n",
              "detectTap": "\treturn ATMO_Status_Success;\n",
              "detectMotion": "\treturn ATMO_Status_Success;\n",
              "detectFreefall": "\treturn ATMO_Status_Success;\n",
              "enableFreefallDetection": "if(ATMO_FXOS8700_EnableFreefallDetection() == ATMO_FXOS8700_Status_Success)\n{\n    return ATMO_Status_Success;\n}\n\nreturn ATMO_Status_Fail;",
              "enableMotionDetection": "if(ATMO_FXOS8700_EnableMotionDetection() == ATMO_FXOS8700_Status_Success)\n{\n    return ATMO_Status_Success;\n}\n\nreturn ATMO_Status_Fail;",
              "enableTapDetection": "if(ATMO_FXOS8700_EnableTapDetection() == ATMO_FXOS8700_Status_Success)\n{\n    return ATMO_Status_Success;\n}\n\nreturn ATMO_Status_Fail;",
              "disableDetection": "if(ATMO_FXOS8700_DisableAllDetection() == ATMO_FXOS8700_Status_Success)\n{\n    return ATMO_Status_Success;\n}\n\nreturn ATMO_Status_Fail;"
            },
            "variables": {},
            "embeddedPropertyConversions": {},
            "codeUserChanged": {
              "setup": false,
              "setEnabled": false,
              "setDisabled": false,
              "setEnabledDisabled": false,
              "getAccelData": false,
              "getAccelX": false,
              "getAccelY": false,
              "getAccelZ": false,
              "getMagData": false,
              "getMagX": false,
              "getMagY": false,
              "getMagZ": false,
              "detectTap": false,
              "detectMotion": false,
              "detectFreefall": false,
              "enableFreefallDetection": false,
              "enableMotionDetection": false,
              "enableTapDetection": false,
              "disableDetection": false
            },
            "i2cInstance": "ATMO_DRIVERINSTANCE_I2C_I2C2",
            "gpioInstance": "ATMO_DRIVERINSTANCE_GPIO_GPIO1",
            "interrupt1Enabled": false,
            "interrupt2Enabled": true,
            "interrupt1Gpio": "ATMO_DEFAULT_GPIO",
            "interrupt2Gpio": "PTD13",
            "motionDetectType": "FXOS8700_MotionDetect",
            "i2cAddress": "0x1E"
          },
          "meta": {
            "editorX": 215,
            "editorY": 31,
            "lastTrigger": "motionDetected"
          },
          "triggers": {
            "triggered": [],
            "accelDataRead": [
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "Func",
                "targetAbility": "trigger"
              }
            ],
            "accelXRead": [],
            "accelYRead": [],
            "accelZRead": [],
            "magDataRead": [],
            "magXRead": [],
            "magYRead": [],
            "magZRead": [],
            "tapDetected": [],
            "motionDetected": [
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "Func",
                "targetAbility": "trigger"
              }
            ],
            "freefallDetected": []
          },
          "interruptAbilities": {
            "trigger": false,
            "setup": false,
            "setEnabled": false,
            "setDisabled": false,
            "setEnabledDisabled": false,
            "getAccelData": false,
            "getAccelX": false,
            "getAccelY": false,
            "getAccelZ": false,
            "getMagData": false,
            "getMagX": false,
            "getMagY": false,
            "getMagZ": false,
            "detectTap": false,
            "detectMotion": false,
            "detectFreefall": false,
            "enableFreefallDetection": false,
            "enableMotionDetection": false,
            "enableTapDetection": false,
            "disableDetection": false
          },
          "abilities": [
            {
              "name": "trigger",
              "triggers": [
                "triggered"
              ]
            },
            {
              "name": "setup",
              "triggers": []
            },
            {
              "name": "setEnabled",
              "triggers": []
            },
            {
              "name": "setDisabled",
              "triggers": []
            },
            {
              "name": "setEnabledDisabled",
              "triggers": []
            },
            {
              "name": "getAccelData",
              "triggers": [
                "accelDataRead"
              ]
            },
            {
              "name": "getAccelX",
              "triggers": [
                "accelXRead"
              ]
            },
            {
              "name": "getAccelY",
              "triggers": [
                "accelYRead"
              ]
            },
            {
              "name": "getAccelZ",
              "triggers": [
                "accelZRead"
              ]
            },
            {
              "name": "getMagData",
              "triggers": [
                "magDataRead"
              ]
            },
            {
              "name": "getMagX",
              "triggers": [
                "magXRead"
              ]
            },
            {
              "name": "getMagY",
              "triggers": [
                "magYRead"
              ]
            },
            {
              "name": "getMagZ",
              "triggers": [
                "magZRead"
              ]
            },
            {
              "name": "detectTap",
              "triggers": [
                "tapDetected"
              ]
            },
            {
              "name": "detectMotion",
              "triggers": [
                "motionDetected"
              ]
            },
            {
              "name": "detectFreefall",
              "triggers": [
                "freefallDetected"
              ]
            },
            {
              "name": "enableFreefallDetection",
              "triggers": []
            },
            {
              "name": "enableMotionDetection",
              "triggers": []
            },
            {
              "name": "enableTapDetection",
              "triggers": []
            },
            {
              "name": "disableDetection",
              "triggers": []
            }
          ]
        },
        {
          "name": "SX9500Touch",
          "type": "EmbeddedSX9500",
          "variants": [
            "embedded",
            "triggers",
            "abilities",
            "properties",
            "variables"
          ],
          "properties": {
            "errorData": {},
            "code": {
              "trigger": "\treturn ATMO_Status_Success;",
              "setup": "\tATMO_SX9500_Config_t config;\n\tconfig.address = ATMO_PROPERTY(SX9500Touch, i2cAddress);\n\tconfig.i2cDriverInstance = ATMO_PROPERTY(SX9500Touch, i2cInstance);\n\tconfig.gpioDriverInstance = ATMO_PROPERTY(SX9500Touch, gpioInstance);\n\tconfig.interruptEnabled = ATMO_PROPERTY(SX9500Touch, interruptEnabled);\n\tconfig.interruptPin = ATMO_PROPERTY(SX9500Touch, interruptGpio);\n\tATMO_SX9500_Init(&config);\n\tATMO_SX9500_RegisterTouchedAbilityHandle(SX9500_Touched_Up, ATMO_ABILITY(SX9500Touch, pressUp));\n\tATMO_SX9500_RegisterTouchedAbilityHandle(SX9500_Touched_Down, ATMO_ABILITY(SX9500Touch, pressDown));\n\tATMO_SX9500_RegisterTouchedAbilityHandle(SX9500_Touched_Left, ATMO_ABILITY(SX9500Touch, pressLeft));\n\tATMO_SX9500_RegisterTouchedAbilityHandle(SX9500_Touched_Right, ATMO_ABILITY(SX9500Touch, pressRight));\n\treturn ATMO_Status_Success;",
              "getTouchData": "",
              "pressUp": "SX9500_TouchState_t touchState;\nATMO_GetBinary(in, &touchState, sizeof(touchState));\nATMO_CreateValueBinary(out, &touchState, sizeof(touchState));\nreturn ATMO_Status_Success;",
              "pressDown": "SX9500_TouchState_t touchState;\nATMO_GetBinary(in, &touchState, sizeof(touchState));\nATMO_CreateValueBinary(out, &touchState, sizeof(touchState));\nreturn ATMO_Status_Success;",
              "pressLeft": "SX9500_TouchState_t touchState;\nATMO_GetBinary(in, &touchState, sizeof(touchState));\nATMO_CreateValueBinary(out, &touchState, sizeof(touchState));\nreturn ATMO_Status_Success;",
              "pressRight": "SX9500_TouchState_t touchState;\nATMO_GetBinary(in, &touchState, sizeof(touchState));\nATMO_CreateValueBinary(out, &touchState, sizeof(touchState));\nreturn ATMO_Status_Success;"
            },
            "variables": {},
            "embeddedPropertyConversions": {},
            "codeUserChanged": {
              "setup": false,
              "getTouchData": false,
              "pressUp": false,
              "pressDown": false,
              "pressLeft": false,
              "pressRight": false
            },
            "i2cInstance": "ATMO_DRIVERINSTANCE_I2C_I2C2",
            "gpioInstance": "ATMO_DRIVERINSTANCE_GPIO_GPIO1",
            "interruptEnabled": true,
            "interruptGpio": "PTA9",
            "i2cAddress": "0x28"
          },
          "meta": {
            "editorX": 710,
            "editorY": 10,
            "lastTrigger": "touchDataRead"
          },
          "triggers": {
            "triggered": [],
            "touchDataRead": [],
            "upPressed": [
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "EmbeddedPageController",
                "targetAbility": "navigateUp"
              }
            ],
            "downPressed": [
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "EmbeddedPageController",
                "targetAbility": "navigateDown"
              }
            ],
            "leftPressed": [
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "EmbeddedPageController",
                "targetAbility": "navigateLeft"
              }
            ],
            "rightPressed": [
              {
                "mapping": {},
                "targetOrder": [],
                "targetElement": "EmbeddedPageController",
                "targetAbility": "navigateRight"
              }
            ]
          },
          "interruptAbilities": {
            "trigger": false,
            "setup": false,
            "getTouchData": false,
            "pressUp": false,
            "pressDown": false,
            "pressLeft": false,
            "pressRight": false
          },
          "abilities": [
            {
              "name": "trigger",
              "triggers": [
                "triggered"
              ]
            },
            {
              "name": "setup",
              "triggers": []
            },
            {
              "name": "getTouchData",
              "triggers": [
                "touchDataRead"
              ]
            },
            {
              "name": "pressUp",
              "triggers": [
                "upPressed",
                "touchDataRead"
              ]
            },
            {
              "name": "pressDown",
              "triggers": [
                "downPressed",
                "touchDataRead"
              ]
            },
            {
              "name": "pressLeft",
              "triggers": [
                "leftPressed",
                "touchDataRead"
              ]
            },
            {
              "name": "pressRight",
              "triggers": [
                "rightPressed",
                "touchDataRead"
              ]
            }
          ]
        },
        {
          "name": "EmbeddedPageController",
          "type": "EmbeddedPageController",
          "variants": [
            "embedded",
            "triggers",
            "abilities",
            "properties",
            "variables",
            "rpk"
          ],
          "properties": {
            "errorData": {},
            "code": {
              "trigger": "\treturn ATMO_Status_Success;",
              "setup": "\n\tATMO_UI_PAGE_CONTROLLER_Config_t config;\n\tconfig.enableUpDownNavLabels = ATMO_PROPERTY(EmbeddedPageController, upDownNavigationLabelsEnabled);\n\tconfig.enableLeftRightNavLabels = ATMO_PROPERTY(EmbeddedPageController, leftRightNavigationLabelsEnabled);\n\tATMO_UI_Page_SetConfiguration(&config);\n    return ATMO_Status_Success;\n\t",
              "displayRootPage": "\n\t\n\tATMO_UI_Page_DisplayRootPage();\n\treturn ATMO_Status_Success;\n\t",
              "navigateUp": "\n\tATMO_UI_Page_ProcessNavButton(ATMO_UI_PAGE_NAV_UP);\n\treturn ATMO_Status_Success;\n\t",
              "navigateDown": "\n\tATMO_UI_Page_ProcessNavButton(ATMO_UI_PAGE_NAV_DOWN);\n\treturn ATMO_Status_Success;\n\t",
              "navigateLeft": "\n\tATMO_UI_Page_ProcessNavButton(ATMO_UI_PAGE_NAV_LEFT);\n\treturn ATMO_Status_Success;\n\t",
              "navigateRight": "\n\tATMO_UI_Page_ProcessNavButton(ATMO_UI_PAGE_NAV_RIGHT);\n\treturn ATMO_Status_Success;\n\t",
              "processTopRightButton": "\n\tATMO_UI_Page_ProcessUserButton(1);\n\treturn ATMO_Status_Success;\n\t",
              "processBottomRightButton": "\n\tATMO_UI_Page_ProcessUserButton(2);\n\treturn ATMO_Status_Success;\n\t",
              "processTopLeftButton": "\n\tATMO_UI_Page_ProcessUserButton(3);\n\treturn ATMO_Status_Success;\n\t",
              "processBottomLeftButton": "\n\tATMO_UI_Page_ProcessUserButton(4);\n\treturn ATMO_Status_Success;\n\t"
            },
            "variables": {},
            "embeddedPropertyConversions": {},
            "codeUserChanged": {
              "setup": false,
              "displayRootPage": false,
              "navigateUp": false,
              "navigateDown": false,
              "navigateLeft": false,
              "navigateRight": false,
              "processTopRightButton": false,
              "processBottomRightButton": false,
              "processTopLeftButton": false,
              "processBottomLeftButton": false
            },
            "upDownNavigationLabelsEnabled": true,
            "leftRightNavigationLabelsEnabled": true
          },
          "meta": {
            "editorX": 855,
            "editorY": 16,
            "lastTrigger": "triggered"
          },
          "triggers": {
            "triggered": [],
            "navigateUp": [],
            "navigateDown": [],
            "navigateLeft": [],
            "navigateRight": [],
            "processTopRightButton": [],
            "processBottomRightButton": [],
            "processTopLeftButton": [],
            "processBottomLeftButton": []
          },
          "interruptAbilities": {
            "trigger": false,
            "setup": false,
            "displayRootPage": false,
            "navigateUp": false,
            "navigateDown": false,
            "navigateLeft": false,
            "navigateRight": false,
            "processTopRightButton": false,
            "processBottomRightButton": false,
            "processTopLeftButton": false,
            "processBottomLeftButton": false
          },
          "abilities": [
            {
              "name": "trigger",
              "triggers": [
                "triggered"
              ]
            },
            {
              "name": "setup",
              "triggers": []
            },
            {
              "name": "displayRootPage",
              "triggers": []
            },
            {
              "name": "navigateUp",
              "triggers": [
...

This file has been truncated, please download it to see its full contents.

ESP8266 MAX30100 Basic code

C/C++
You need the Oxullo MAX30100, Wire, and ESP8266 Core libraries for this one to work. This is just the main logic for the other one but helps in debugging.
/*
Arduino-MAX30100 oximetry / heart rate integrated sensor library
Copyright (C) 2016  OXullo Intersecans <x@brainrapers.org>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <Wire.h>
#include "MAX30100_PulseOximeter.h"

#define REPORTING_PERIOD_MS     1000

// PulseOximeter is the higher level interface to the sensor
// it offers:
//  * beat detection reporting
//  * heart rate calculation
//  * SpO2 (oxidation level) calculation
PulseOximeter pox;

uint32_t tsLastReport = 0;

int counter=0;


// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
    Serial.println("Beat!");
    counter=counter+1;
    Serial.println(counter);
}

void setup()
{
    Wire.begin(D1, D2); // sda, scl
    Serial.begin(115200);

    Serial.print("Initializing pulse oximeter..");

    // Initialize the PulseOximeter instance
    // Failures are generally due to an improper I2C wiring, missing power supply
    // or wrong target chip
    if (!pox.begin()) {
        Serial.println("FAILED");
        for(;;);
    } else {
        Serial.println("SUCCESS");
    }

    // The default current for the IR LED is 50mA and it could be changed
    //   by uncommenting the following line. Check MAX30100_Registers.h for all the
    //   available options.
    // pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);

    // Register a callback for the beat detection
    pox.setOnBeatDetectedCallback(onBeatDetected);
}

void loop()
{
    // Make sure to call update as fast as possible
    pox.update();

    // Asynchronously dump heart rate and oxidation levels to the serial
    // For both, a value of 0 means "invalid"
    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        Serial.print("Heart rate:");
        Serial.print(pox.getHeartRate());
        Serial.print("bpm / SpO2:");
        Serial.print(pox.getSpO2());
        Serial.println("%");

        tsLastReport = millis();
    }
    if (counter>=16){
      counter=0;
      Serial.println("Does it work?");
    }
  
}

secrets

C/C++
Grab the ESP8266+ MAX30100 to publish to AWS IoT file and this one into a folder and open the other one. Just input your values correctly.
#include <pgmspace.h>

#define SECRET

const char ssid[] = "WiFiSSID";
const char pass[] = "WiFiPASS";

#define THINGNAME "WelcomeTest"

int8_t TIME_ZONE = -5; //NYC(USA): -5 UTC
//#define USE_SUMMER_TIME_DST  //uncomment to use DST

const char MQTT_HOST[] = "xxxxxxxxx.iot.us-east-1.amazonaws.com";

// Obtain First CA certificate for Amazon AWS
// https://docs.aws.amazon.com/iot/latest/developerguide/managing-device-certs.html#server-authentication
// Copy contents from CA certificate here 
static const char cacert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
)EOF";

// Copy contents from XXXXXXXX-certificate.pem.crt here 
static const char client_cert[] PROGMEM = R"KEY(
-----BEGIN CERTIFICATE-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
)KEY";

// Copy contents from  XXXXXXXX-private.pem.key here 
static const char privkey[] PROGMEM = R"KEY(
-----BEGIN RSA PRIVATE KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END RSA PRIVATE KEY-----
)KEY";

Lambda snippet

JavaScript
This is just a snippet of the whole implementation, you know how amazon is when providing lambdas and credentials
var Alexa = require('alexa-sdk');

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);

    alexa.dynamoDBTableName = 'sampleLangaugeTable'; // creates new table for session.attributes

    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
    'LaunchRequest': function() { //Executes when a new session is launched
        //if (!this.attributes['myLangauge']) {
            this.emit('LaunchIntent');
        //} else {
        //    this.emit('TestIntent');
        //}
    },

    'LaunchIntent': function() {
        this.emit(':ask', "Hi, what do you wish to know? Your Bench, Deadlift, Squat PRs, Or maybe some data from the sensors?");
    },

    'LanguageIntent': function() {
        this.attributes['myLangauge'] = this.event.request.intent.slots.myLangauge.value;
        this.emit(':ask', "I got it.");
    },

    'TestIntent': function() {
        this.emit(':tell', "I still remember that your language is, " + this.attributes['myLangauge']);
    },
   
    'telematico': function() {
        this.attributes['bench'] = this.event.request.intent.slots.bench.value;
        this.emit(':ask', "got it, yeah buddy");
    },
    
    'tiesto': function() {
        this.emit(':tell', "I remember that your bench is, " + this.attributes['bench']);
    },
    
    'temperature': function() {
        this.emit(':ask', "N X P Rapid I O T Prototyping kit determines that the temperature is" + this.attributes['temperature']);
    },
    
    'setup': function() {
        this.emit(':ask', "How much you bench?");
    }
};

ESP8266+ MAX30100 to publish to AWS IoT

C/C++
Set your credentials properly in the secrets file, select your topic, and you are good to go.
To change the message just play with the Arduino Json library
/*
Arduino-MAX30100 oximetry / heart rate integrated sensor library
Copyright (C) 2016  OXullo Intersecans <x@brainrapers.org>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <Wire.h>
#include "MAX30100_PulseOximeter.h" //for the oximeter

#define REPORTING_PERIOD_MS     1000

PulseOximeter pox;

uint32_t tsLastReport = 0;
//////////////////////////////////////////////////////////


#ifdef ESP32
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#else
#error Platform not supported
#endif
#include <WiFiClientSecure.h>
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson (use v6.xx)
#include <time.h>
#define emptyString String()

//Follow instructions from https://github.com/debsahu/ESP-MQTT-AWS-IoT-Core/blob/master/doc/README.md
//Enter values in secrets.h 
#include "secrets.h"

#ifndef PIO_PLATFORM
//#define USE_PUB_SUB  //uncomment to use PubSubClient(https://github.com/knolleary/pubsubclient)
#endif

#if !(ARDUINOJSON_VERSION_MAJOR == 6 and ARDUINOJSON_VERSION_MINOR == 7)
#error "Install ArduinoJson v6.7.0-beta"
#endif

const int MQTT_PORT = 8883;
const char MQTT_SUB_TOPIC[] = "YOUR TOPIC";
const char MQTT_PUB_TOPIC[] = "YOUR TOPIC";

#ifdef USE_SUMMER_TIME_DST
uint8_t DST = 1;
#else
uint8_t DST = 0;
#endif

WiFiClientSecure net;

#ifdef ESP8266
BearSSL::X509List cert(cacert);
BearSSL::X509List client_crt(client_cert);
BearSSL::PrivateKey key(privkey);
#endif

#ifdef USE_PUB_SUB
#include <PubSubClient.h>
#if defined(USE_PUB_SUB) and defined(PIO_PLATFORM) // PIO has issues, needs MQTT.h definition or else freaks out
#include <MQTT.h>
#endif
PubSubClient client(net);
#else
#include <MQTT.h>
MQTTClient client;
#endif

unsigned long lastMillis = 0;
time_t now;
time_t nowish = 1510592825;

int counter=0;
int counter1=0;

void onBeatDetected()
{
    Serial.println("Beat!");
    counter=counter+1;
    Serial.println(counter);
}

void NTPConnect(void)
{
  Serial.print("Setting time using SNTP");
  configTime(TIME_ZONE * 3600, DST * 3600, "pool.ntp.org", "time.nist.gov");
  now = time(nullptr);
  while (now < nowish)
  {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("done!");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));
}

#ifdef USE_PUB_SUB

void messageReceivedPubSub(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Received [");
  Serial.print(topic);
  Serial.print("]: ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void pubSubErr(int8_t MQTTErr)
{
  if (MQTTErr == MQTT_CONNECTION_TIMEOUT)
    Serial.print("Connection tiemout");
  else if (MQTTErr == MQTT_CONNECTION_LOST)
    Serial.print("Connection lost");
  else if (MQTTErr == MQTT_CONNECT_FAILED)
    Serial.print("Connect failed");
  else if (MQTTErr == MQTT_DISCONNECTED)
    Serial.print("Disconnected");
  else if (MQTTErr == MQTT_CONNECTED)
    Serial.print("Connected");
  else if (MQTTErr == MQTT_CONNECT_BAD_PROTOCOL)
    Serial.print("Connect bad protocol");
  else if (MQTTErr == MQTT_CONNECT_BAD_CLIENT_ID)
    Serial.print("Connect bad Client-ID");
  else if (MQTTErr == MQTT_CONNECT_UNAVAILABLE)
    Serial.print("Connect unavailable");
  else if (MQTTErr == MQTT_CONNECT_BAD_CREDENTIALS)
    Serial.print("Connect bad credentials");
  else if (MQTTErr == MQTT_CONNECT_UNAUTHORIZED)
    Serial.print("Connect unauthorized");
}

#else

void messageReceived(String &topic, String &payload)
{
  Serial.println("Recieved [" + topic + "]: " + payload);
}

void lwMQTTErr(lwmqtt_err_t reason)
{
  if (reason == lwmqtt_err_t::LWMQTT_SUCCESS)
    Serial.print("Success");
  else if (reason == lwmqtt_err_t::LWMQTT_BUFFER_TOO_SHORT)
    Serial.print("Buffer too short");
  else if (reason == lwmqtt_err_t::LWMQTT_VARNUM_OVERFLOW)
    Serial.print("Varnum overflow");
  else if (reason == lwmqtt_err_t::LWMQTT_NETWORK_FAILED_CONNECT)
    Serial.print("Network failed connect");
  else if (reason == lwmqtt_err_t::LWMQTT_NETWORK_TIMEOUT)
    Serial.print("Network timeout");
  else if (reason == lwmqtt_err_t::LWMQTT_NETWORK_FAILED_READ)
    Serial.print("Network failed read");
  else if (reason == lwmqtt_err_t::LWMQTT_NETWORK_FAILED_WRITE)
    Serial.print("Network failed write");
  else if (reason == lwmqtt_err_t::LWMQTT_REMAINING_LENGTH_OVERFLOW)
    Serial.print("Remaining length overflow");
  else if (reason == lwmqtt_err_t::LWMQTT_REMAINING_LENGTH_MISMATCH)
    Serial.print("Remaining length mismatch");
  else if (reason == lwmqtt_err_t::LWMQTT_MISSING_OR_WRONG_PACKET)
    Serial.print("Missing or wrong packet");
  else if (reason == lwmqtt_err_t::LWMQTT_CONNECTION_DENIED)
    Serial.print("Connection denied");
  else if (reason == lwmqtt_err_t::LWMQTT_FAILED_SUBSCRIPTION)
    Serial.print("Failed subscription");
  else if (reason == lwmqtt_err_t::LWMQTT_SUBACK_ARRAY_OVERFLOW)
    Serial.print("Suback array overflow");
  else if (reason == lwmqtt_err_t::LWMQTT_PONG_TIMEOUT)
    Serial.print("Pong timeout");
}

void lwMQTTErrConnection(lwmqtt_return_code_t reason)
{
  if (reason == lwmqtt_return_code_t::LWMQTT_CONNECTION_ACCEPTED)
    Serial.print("Connection Accepted");
  else if (reason == lwmqtt_return_code_t::LWMQTT_UNACCEPTABLE_PROTOCOL)
    Serial.print("Unacceptable Protocol");
  else if (reason == lwmqtt_return_code_t::LWMQTT_IDENTIFIER_REJECTED)
    Serial.print("Identifier Rejected");
  else if (reason == lwmqtt_return_code_t::LWMQTT_SERVER_UNAVAILABLE)
    Serial.print("Server Unavailable");
  else if (reason == lwmqtt_return_code_t::LWMQTT_BAD_USERNAME_OR_PASSWORD)
    Serial.print("Bad UserName/Password");
  else if (reason == lwmqtt_return_code_t::LWMQTT_NOT_AUTHORIZED)
    Serial.print("Not Authorized");
  else if (reason == lwmqtt_return_code_t::LWMQTT_UNKNOWN_RETURN_CODE)
    Serial.print("Unknown Return Code");
}
#endif

void connectToMqtt(bool nonBlocking = false)
{
  Serial.print("MQTT connecting ");
  while (!client.connected())
  {
    if (client.connect(THINGNAME))
    {
      Serial.println("connected!");
      if (!client.subscribe(MQTT_SUB_TOPIC))
#ifdef USE_PUB_SUB
        pubSubErr(client.state());
#else
        lwMQTTErr(client.lastError());
#endif
    }
    else
    {
      Serial.print("failed, reason -> ");
#ifdef USE_PUB_SUB
      pubSubErr(client.state());
#else
      lwMQTTErrConnection(client.returnCode());
#endif
      if (!nonBlocking)
      {
        Serial.println(" < try again in 5 seconds");
        delay(5000);
      }
      else
      {
        Serial.println(" <");
      }
    }
    if (nonBlocking)
      break;
  }
}

void connectToWiFi(String init_str)
{
  if (init_str != emptyString)
    Serial.print(init_str);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(1000);
  }
  if (init_str != emptyString)
    Serial.println("ok!");
}

void checkWiFiThenMQTT(void)
{
  connectToWiFi("Checking WiFi");
  connectToMqtt();
}

unsigned long previousMillis = 0;
const long interval = 5000;

void checkWiFiThenMQTTNonBlocking(void)
{
  connectToWiFi(emptyString);
  if (millis() - previousMillis >= interval && !client.connected()) {
    previousMillis = millis();
    connectToMqtt(true);
  }
}

void checkWiFiThenReboot(void)
{
  connectToWiFi("Checking WiFi");
  Serial.print("Rebooting");
  ESP.restart();
}

void sendData(void)
{
  DynamicJsonDocument jsonBuffer;
  JsonObject root = jsonBuffer.to<JsonObject>();
  root["variable"] = 1;
  root["heartrate"] = 2;
  root["Heart Rate "] = pox.getHeartRate();
  root["SpO2 "] = pox.getSpO2();
  Serial.printf("Sending  [%s]: ", MQTT_PUB_TOPIC);
  serializeJson(root, Serial);
  Serial.println();
  char shadow[measureJson(root) + 1];
  serializeJson(root, shadow, sizeof(shadow));
#ifdef USE_PUB_SUB
  if (!client.publish(MQTT_PUB_TOPIC, shadow, false))
    pubSubErr(client.state());
#else
  if (!client.publish(MQTT_PUB_TOPIC, shadow, false, 0))
    lwMQTTErr(client.lastError());
#endif
}

void setup()
{
  pinMode(D3, OUTPUT);
  Wire.begin(D1, D2); // sda, scl
  Serial.begin(115200);
  delay(5000);
  Serial.println();
  Serial.println();
#ifdef ESP32
  WiFi.setHostname(THINGNAME);
#else
  WiFi.hostname(THINGNAME);
#endif
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
  connectToWiFi(String("Attempting to connect to SSID: ") + String(ssid));

  NTPConnect();

#ifdef ESP32
  net.setCACert(cacert);
  net.setCertificate(client_cert);
  net.setPrivateKey(privkey);
#else
  net.setTrustAnchors(&cert);
  net.setClientRSACert(&client_crt, &key);
#endif

#ifdef USE_PUB_SUB
  client.setServer(MQTT_HOST, MQTT_PORT);
  client.setCallback(messageReceivedPubSub);
#else
  client.begin(MQTT_HOST, MQTT_PORT, net);
  client.onMessage(messageReceived);
#endif
  connectToMqtt();

  Serial.print("Initializing pulse oximeter..");

  // Initialize the PulseOximeter instance
  // Failures are generally due to an improper I2C wiring, missing power supply
  // or wrong target chip
  if (!pox.begin()) {
    Serial.println("FAILED");
    for(;;);
  } else {
    Serial.println("SUCCESS");
  }

    // The default current for the IR LED is 50mA and it could be changed
    //   by uncommenting the following line. Check MAX30100_Registers.h for all the
    //   available options.
    // pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);

    // Register a callback for the beat detection
  pox.setOnBeatDetectedCallback(onBeatDetected);
  
}

void loop()
{
  pox.update();

    // Asynchronously dump heart rate and oxidation levels to the serial
    // For both, a value of 0 means "invalid"
  if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
      Serial.print("Heart rate:");
      Serial.print(pox.getHeartRate());
      Serial.print("bpm / SpO2:");
      Serial.print(pox.getSpO2());
      Serial.println("%");

      tsLastReport = millis();
  }
  now = time(nullptr);
  //if (!client.connected())
  //{
    //checkWiFiThenMQTT();
    //checkWiFiThenMQTTNonBlocking();
    //checkWiFiThenReboot();
  //}
  //else
  //{
  client.loop();
    //if (millis() - lastMillis > 5000)
  if (counter>=5)
  {
    counter=0;
    Serial.println("Does it Work?");
    //lastMillis = millis();
    sendData();
  }
  //}
}

implementation JSON

JSON
for ASK kit.
{
    "interactionModel": {
        "languageModel": {
            "invocationName": "fitness tracker",
            "intents": [
                {
                    "name": "AMAZON.FallbackIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "TestIntent",
                    "slots": [],
                    "samples": [
                        "my number of steps is",
                        "how many teps did I took",
                        "Tell me my number of steps",
                        "how many steps"
                    ]
                },
                {
                    "name": "benchintent",
                    "slots": [],
                    "samples": [
                        "I want to know my last one",
                        "I want to know my last bench",
                        "How much did I benched"
                    ]
                },
                {
                    "name": "lebench",
                    "slots": [
                        {
                            "name": "bench",
                            "type": "Bench_numbers"
                        }
                    ],
                    "samples": [
                        "my bench press is {bench}",
                        "I bench pressed {bench}
                    ]
                },
                                {
                    "name": "deadliftintent",
                    "slots": [],
                    "samples": [
                        "I want to know my last one",
                        "I want to know my last deadlift",
                        "How much did I deadlifted"
                    ]
                },
                {
                    "name": "ledeadlift",
                    "slots": [
                        {
                            "name": "deadlift",
                            "type": "deadlift_numbers"
                        }
                    ],
                    "samples": [
                        "my deadlift is {deadlift}",
                        "I deadlifted {deadlift}
                    ]
                },
                                {
                    "name": "squatintent",
                    "slots": [],
                    "samples": [
                        "I want to know my last one",
                        "I want to know my last squat",
                        "How much did I squatted"
                    ]
                },
                {
                    "name": "lesquat",
                    "slots": [
                        {
                            "name": "squat",
                            "type": "Squat_numbers"
                        }
                    ],
                    "samples": [
                        "my squat is {squat}",
                        "I squatted {squat}
                    ]
                },
                {
                    "name": "temperature",
                    "slots": [],
                    "samples": [
                        "tell me the temperature",
                        "how much is my temperature"
                    ]
                },
                {
                    "name": "Heart Rate",
                    "slots": [],
                    "samples": [
                        "tell me my heart rate",
                        "how much is my heart rate"
                    ]
                },

                {
                    "name": "setup",
                    "slots": [],
                    "samples": [
                        "set up my new bench press"
                    ]
                },
                {
                    "name": "setup1",
                    "slots": [],
                    "samples": [
                        "set up my new squat"
                    ]
                },
                {
                    "name": "setup2",
                    "slots": [],
                    "samples": [
                        "set up my new deadlift"
                    ]
                }
            ],
            "types": [
                {
                    "name": "Bench_numbers",
                    "values": [
                        {
                            "name": {
                                "value": "52"
                            }
                        },
                        {
                            "name": {
                                "value": "53"
                            }
                        },
                        {
                            "name": {
                                "value": "295"
                            }
                        },
                        {
                            "name": {
                                "value": "355"
                            }
                        },
                        {
                            "name": {
                                "value": "345"
                            }
                        }
                    ]
                },
                                {
                    "name": "Squat_numbers",
                    "values": [
                        {
                            "name": {
                                "value": "52"
                            }
                        },
                        {
                            "name": {
                                "value": "53"
                            }
                        },
                        {
                            "name": {
                                "value": "295"
                            }
                        },
                        {
                            "name": {
                                "value": "355"
                            }
                        },
                        {
                            "name": {
                                "value": "345"
                            }
                        }
                    ]
                },
                                {
                    "name": "deadlift_numbers",
                    "values": [
                        {
                            "name": {
                                "value": "52"
                            }
                        },
                        {
                            "name": {
                                "value": "53"
                            }
                        },
                        {
                            "name": {
                                "value": "295"
                            }
                        },
                        {
                            "name": {
                                "value": "355"
                            }
                        },
                        {
                            "name": {
                                "value": "345"
                            }
                        }
                    ]
                }
            ]
        }
    }
}

Credits

EdOliver

EdOliver

38 projects • 74 followers
Engineer, Scientist, Maker. Entrepreneur and Futurist.

Comments