How to read multiple sensor and send the data to ThingSpeak? - iot

I have a problem with my code. When I test it without ThingSpeak library, my sensor values (especially for analogRead on fireLevel dan gasLevel) are there (not 0). But when I use ThingSpeak library for send the data, the fireLevel dan gasLevel show 0 for the values. Any solutions for my code, thanks
I'm still learning
The sensor that I used:
DHT11
KY-026
MQ-135
and for the NodeMCU I used ESP32 type
#include <WiFi.h>
#include "ThingSpeak.h"
#include <SPI.h>
#include <Wire.h>
#include <DHT.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
const char* ssid = "SECRET_SSID";
const char* password = "SECRET_PASSWORD";
WiFiClient client;
unsigned long channelNum = X;
const char* APIKey = "SECRET_KEY";
#define AIRQ_SENSOR 2 // ESP32 pin GIP2 connected to mq135 sensor
#define DHT_SENSOR_PIN 13 // ESP32 pin GIOP13 connected to DHT11 sensor
#define DHT_SENSOR_TYPE DHT11
#define FIRE_SENSOR_ANALOG 14 // ESP32 pin GIP14 connected to Fire sensor
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
DHT dht_sensor(DHT_SENSOR_PIN, DHT_SENSOR_TYPE);
float humi, tempC, gasLevel, fireLevel;
String quality = "";
const uint8_t bitmap19[] = {0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x40, 0x00, 0x7f, 0x60, 0x00, 0xff, 0xe0, 0x00, 0xff, 0xf0, 0x06, 0xff, 0xf0, 0x07, 0xff, 0xf8, 0x07, 0xff, 0xf8, 0x0f, 0xf7, 0xf8, 0x0f, 0xe7, 0xf8, 0x1f, 0xe3, 0xfc, 0x1f, 0xc1, 0xfc, 0x3f, 0x80, 0xfc, 0x3f, 0x80, 0xf8, 0x1f, 0x00, 0xf8, 0x1f, 0x00, 0xf0, 0x0f, 0x00, 0xe0, 0x07, 0x80, 0xc0, 0x01, 0x81, 0x00};
void setup() {
Serial.begin(9600);
dht_sensor.begin(); // initialize the DHT sensor
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(50, 0);
display.println("Air");
display.setTextSize(1);
display.setCursor(23, 20);
display.println("Quality Monitor");
display.display();
delay(1200);
display.clearDisplay();
WiFi.mode(WIFI_STA);
ThingSpeak.begin(client);
}
void fireSensor() {
fireLevel = analogRead(FIRE_SENSOR_ANALOG);
Serial.println("fire level: " + String(fireLevel));
if(fireLevel < 2000) {
display.drawBitmap(90, 35, bitmap19, 24, 24, 1);
}
else {
display.clearDisplay();
}
}
void temphSensor() {
// read humidity
humi = dht_sensor.readHumidity();
// read temperature in Celsius
tempC = dht_sensor.readTemperature();
// check whether the reading is successful or not
if ( isnan(tempC) || isnan(humi)) {
Serial.println("Failed to read from DHT sensor!");
} else {
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 35);
display.println("Tmp:");
display.setCursor(30, 35);
display.println(tempC);
display.setCursor(64, 35);
display.println("C");
display.setCursor(0, 50);
display.println("RH:");
display.setCursor(30, 50);
display.println(humi);
display.setCursor(64, 50);
display.println("%");
}
}
void airqSensor() {
gasLevel = analogRead(AIRQ_SENSOR);
Serial.println("gas Level: " + String(gasLevel));
if(gasLevel < 500) {
quality = "Good";
}
else if(gasLevel < 750) {
// avg 750
quality = "Moderate";
}
else if(gasLevel < 1500) {
// avg 1500
quality = "Unhealty";
}
else {
// 2000 >
quality = "Hazardous";
}
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(30, 5);
display.println("Air Quality");
display.setCursor(35, 20);
display.println(quality);
}
void writeThingSpeak() {
ThingSpeak.setField(1, tempC);
ThingSpeak.setField(2, humi);
ThingSpeak.setField(3, gasLevel);
ThingSpeak.setField(4, fireLevel);
int x = ThingSpeak.writeFields(channelNum, APIKey);
if(x == 200) {
Serial.println("Channel update successful.");
}
else {
Serial.println("Problem updating channel. HTTP error code " + String(x));
}
delay(15000);
}
void loop() {
display.clearDisplay();
if(WiFi.status() != WL_CONNECTED){
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
while(WiFi.status() != WL_CONNECTED){
WiFi.begin(ssid, password); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
Serial.print(".");
delay(5000);
}
Serial.println("\nConnected.");
}
fireSensor();
airqSensor();
temphSensor();
display.display();
writeThingSpeak();
}

After further search I found a solution about my question. The problem is I used ADC2 for my sensor (ex: MQ-135 and KY-026) which is used to read an analog. In this case I put my sensor on GPIO2 and GPIO4, which is among the ADC2.
List of ADC2s are: GPIO pins 0, 2, 4, 12, 13, 14, 15, 25, 26 and 27.
So, instead use ADC2 that originally if you used a WiFi connection on your ESP32, just use ADC1.
List of ADC1s are: GPIO pins 32, 33, 34, 35, 36, 37, 38 and 39.
When I changed my AO pins for both of my sensors (MQ-135 and KY-026) to GPIO34 and 35 it worked!
reference: esp32 pinout reference

Related

Using HID keyboard and the iOS soft-keyboard combined

I've been using nRF52840, SDK 17.0.2, with the example code for HID over BLE keyboard.
When connecting to an iOS phone, the HID keyboard promotes the iOS soft-keyboard, so not input is enabled from the phone's user.
I would like to enable the iOS soft-keyboard while BLE connected with the nRF.
I am using the hid_init configuration and the eject-keyboard key sending, described in here:
Bluetooth LE HID Eject Key Code?
Another source for the above code:
https://github.com/Rallare/nrf51_ble_app_hids_kbd_consumercontrol/blob/master/main.c
However, sending the key will not enable the keyboard unless the phone is currently in a text field. If not in a text field, the key is ignored.
I've also tried sending the following sequence to enable the keyboard:
report key modifier release
*{0, 0x0B, 0x08, true} // Home
{0, 0x2C, 0x08, true} //spotlight
{0, 0x52, 0, true} // Up Arrow
{0, 0x04, 0x08, true} // Select All
{0, 0x2A, 0, true} // Backspace
{1, 0x01, 0, true} // eject
{0, 0x2C, 0x08, true} //spotlight*
But, this solution is not stable and mostly does not work.
I also use shortcuts and keyboard commands to lunch apps, in the project, but could not find something that might help with my issue.
This is the hid configuration I use:
*static void hids_init(void)
{
ret_code_t err_code;
ble_hids_init_t hids_init_obj;
ble_hids_inp_rep_init_t * p_input_report;
ble_hids_outp_rep_init_t * p_output_report;
ble_hids_feature_rep_init_t * p_feature_report;
uint8_t hid_info_flags;
static ble_hids_inp_rep_init_t input_report_array[2];
static ble_hids_outp_rep_init_t output_report_array[1];
static ble_hids_feature_rep_init_t feature_report_array[1];
static uint8_t report_map_data[] =
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report Id (1)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0xe0, // Usage Minimum (224)
0x29, 0xe7, // Usage Maximum (231)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Constant) reserved byte(1)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (Page# for LEDs)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x91, 0x02, // Output (Data, Variable, Absolute), Led report
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output (Data, Variable, Absolute), Led report
padding
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x65, // Logical Maximum (101)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0x00, // Usage Minimum (0)
0x29, 0x65, // Usage Maximum (101)
0x81, 0x00, // Input (Data, Array) Key array(6 bytes)
0x09, 0x05, // Usage (Vendor Defined)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8 bit)
0x95, 0x02, // Report Count (2)
0xB1, 0x02, // Feature (Data, Variable, Absolute)
0xC0, // End Collection (Application)
// Report ID 2: Advanced buttons
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // Report Id (2)
0x15, 0x00, // Logical minimum (0)
0x25, 0x01, // Logical maximum (1)
0x0A, 0xAE, 0x01, // Usage (AL Keyboard Layout)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x81, 0x06, // Input (Data,Value,Relative,Bit Field)
0xC0 // End Collection
};
memset((void *)input_report_array, 0,
2*sizeof(ble_hids_inp_rep_init_t));
memset((void *)output_report_array, 0,
sizeof(ble_hids_outp_rep_init_t));
memset((void *)feature_report_array, 0,
sizeof(ble_hids_feature_rep_init_t));
// Initialize HID Service
p_input_report = &input_report_array[INPUT_REPORT_KEYS_INDEX];
p_input_report->max_len = INPUT_REPORT_KEYS_MAX_LEN;
p_input_report->rep_ref.report_id = INPUT_REP_REF_ID;
p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;
p_input_report->sec.cccd_wr = SEC_JUST_WORKS;
p_input_report->sec.wr = SEC_JUST_WORKS;
p_input_report->sec.rd = SEC_JUST_WORKS;
// Initialize HID Service
p_input_report = &input_report_array[INPUT_REPORT_TOGGLE_INDEX];
p_input_report->max_len = INPUT_REPORT_KEYS_MAX_LEN;
p_input_report->rep_ref.report_id = INPUT_REP_TOGGLE_ID;
p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;
p_input_report->sec.cccd_wr = SEC_JUST_WORKS;
p_input_report->sec.wr = SEC_JUST_WORKS;
p_input_report->sec.rd = SEC_JUST_WORKS;
p_output_report = &output_report_array[OUTPUT_REPORT_INDEX];
p_output_report->max_len = OUTPUT_REPORT_MAX_LEN;
p_output_report->rep_ref.report_id = OUTPUT_REP_REF_ID;
p_output_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_OUTPUT;
p_output_report->sec.wr = SEC_JUST_WORKS;
p_output_report->sec.rd = SEC_JUST_WORKS;
p_feature_report = &feature_report_array[FEATURE_REPORT_INDEX];
p_feature_report->max_len = FEATURE_REPORT_MAX_LEN;
p_feature_report->rep_ref.report_id = FEATURE_REP_REF_ID;
p_feature_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_FEATURE;
p_feature_report->sec.rd = SEC_JUST_WORKS;
p_feature_report->sec.wr = SEC_JUST_WORKS;
hid_info_flags = HID_INFO_FLAG_REMOTE_WAKE_MSK |
HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK;
memset(&hids_init_obj, 0, sizeof(hids_init_obj));
hids_init_obj.evt_handler = on_hids_evt;
hids_init_obj.error_handler = service_error_handler;
hids_init_obj.is_kb = true;
hids_init_obj.is_mouse = false;
hids_init_obj.inp_rep_count = 2;
hids_init_obj.p_inp_rep_array = input_report_array;
hids_init_obj.outp_rep_count = 1;
hids_init_obj.p_outp_rep_array = output_report_array;
hids_init_obj.feature_rep_count = 1;
hids_init_obj.p_feature_rep_array = feature_report_array;
hids_init_obj.rep_map.data_len = sizeof(report_map_data);
hids_init_obj.rep_map.p_data = report_map_data;
hids_init_obj.hid_information.bcd_hid =BASE_USB_HID_SPEC_VERSION;
hids_init_obj.hid_information.b_country_code = 0;
hids_init_obj.hid_information.flags = hid_info_flags;
hids_init_obj.included_services_count = 0;
hids_init_obj.p_included_services_array = NULL;
hids_init_obj.rep_map.rd_sec = SEC_JUST_WORKS;
hids_init_obj.hid_information.rd_sec = SEC_JUST_WORKS;
hids_init_obj.boot_kb_inp_rep_sec.cccd_wr = SEC_JUST_WORKS;
hids_init_obj.boot_kb_inp_rep_sec.rd = SEC_JUST_WORKS;
hids_init_obj.boot_kb_outp_rep_sec.rd = SEC_JUST_WORKS;
hids_init_obj.boot_kb_outp_rep_sec.wr = SEC_JUST_WORKS;
hids_init_obj.protocol_mode_rd_sec = SEC_JUST_WORKS;
hids_init_obj.protocol_mode_wr_sec = SEC_JUST_WORKS;
hids_init_obj.ctrl_point_wr_sec = SEC_JUST_WORKS;
err_code = ble_hids_init(&m_hids, &hids_init_obj);
APP_ERROR_CHECK(err_code);
}*
Tnx for any help given.

Sending Deauthentication Packets by esp8266

I am trying to implement a simple WiFi deauther using my nodemcu but i can't see any disconnection b/w AP(my android's hotspot) & Station ( my second android device)
But when i am using a third party tool like Wi-PWN ( available on GitHub ) , is working.
So its clear that i am doing something wrong in Deauthentication process
Here is some parts of code
// Channel to perform deauth
uint8_t channel = 0;
// Packet buffer
uint8_t packet_buffer[128];
// DeAuth template
uint8_t template_da[26] = {
0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xCC, 0xCC, 0xCC, 0xCC,
0xCC, 0xCC, 0x00, 0x00, 0x01,
0x00};
uint16_t create_packet(uint8_t *buf, uint8_t *client, uint8_t *ap, uint8_t type)
{
int i = 0;
memcpy(buf, template_da, 26);
// Destination
memcpy(buf + 4, client, ETH_MAC_LEN);
// Sender
memcpy(buf + 10, ap, ETH_MAC_LEN);
buf[0] = type;
return 26;
}
/* Sends deauth packets. */
void deauth(uint8_t *c, uint8_t *ap, uint16_t seq)
{
uint8_t i = 0;
uint16_t sz = 0;
sz = create_packet(packet_buffer, c, ap, 0xc0); // 0xc0 for deauth
wifi_send_pkt_freedom(packet_buffer, sz, 0);
sz = create_packet(packet_buffer, c, ap, 0xa0); // xa0 for disassociation
wifi_send_pkt_freedom(packet_buffer, sz, 0);
delay(1);
}
}
Edit : I know the mac address of both AP & Station so there could be no mistake in filling mac while creating packet.

SHA256 Swift to Objective C equivalence

Hello everyone I'm working for the first time with SHA256 and I'm trying to follow a tutorial on this my problem is to write the equivalence in Objective C of SHA 256. I'm trying to understand the function that I show you below but I still have problems on how to find the equivalence in Objective C of this Swift function
let rsa2048Asn1Header:[UInt8] = [
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00
]
private func sha256(data : Data) -> String {
var keyWithHeader = Data(bytes: rsa2048Asn1Header)
keyWithHeader.append(data)
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
keyWithHeader.withUnsafeBytes {
_ = CC_SHA256($0, CC_LONG(keyWithHeader.count), &hash)
}
return Data(hash).base64EncodedString()
}
Can you help me ?
Working with raw bytes in Objective-C is generally a little more straightforward than Swift. An implementation like this should be equivalent.
#define RSA_2048_ASN1_HDR_LEN 24
- (NSString *)sha256:(NSData *)data {
NSMutableData *keyWithHeader = [NSMutableData dataWithBytes:rsa2048Asn1Header length:RSA_2048_ASN1_HDR_LEN];
[keyWithHeader appendData:data];
UInt8 hash[CC_SHA256_DIGEST_LENGTH] = { 0 };
CC_SHA256(keyWithHeader.bytes, (CC_LONG) keyWithHeader.length, hash);
return [[NSData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH] base64EncodedStringWithOptions:0];
}
Note that you'll also need to import the common crypto library into your Objective-C file as well:
#import <CommonCrypto/CommonDigest.h>

iOS SDL2 OpenGL ES Cannot Draw Texture

I have been trying to follow the below example but using iOS/Xcode instead of VS2015 (which shows an example of an Android cross-platform project).
Youtube Link
I cannot get the code to display any of my texture at all. No matter what I try I only get a small white rectangle. What am I doing wrong?
This should be OpenGL ES1.x so no shaders should be required.
#import <Foundation/Foundation.h>
#include "SDL.h"
#include <time.h>
#include "SDL_opengles.h"
#define FALSE 0
#define TRUE 1
#ifndef BOOL
#define BOOL int
#endif
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 480
GLuint g_Texture = 0;
BOOL g_Running = TRUE;
SDL_Window *g_SDLWindow = NULL;
SDL_Surface *g_SDLSurface = NULL;
SDL_Renderer *g_SDLRenderer = NULL;
SDL_Texture *g_SDLTexture = NULL;
int g_ScreenHeight = SCREEN_HEIGHT;
int g_ScreenWidth = SCREEN_WIDTH;
unsigned char treeData[420] = {
0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x10, 0x00, 0x20, 0x08, 0x82, 0x00, 0x00, 0x00, 0x00, 0x01,
0x16, 0x1D, 0x38, 0xFF, 0x10, 0x50, 0x6C, 0xFF, 0x83, 0x16, 0x1D, 0x38,
0xFF, 0x00, 0x10, 0x50, 0x6C, 0xFF, 0x82, 0x16, 0x1D, 0x38, 0xFF, 0x82,
0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x81, 0x16, 0x1D,
0x38, 0xFF, 0x00, 0x10, 0x50, 0x6C, 0xFF, 0x84, 0x16, 0x1D, 0x38, 0xFF,
0x83, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x82, 0x16,
0x1D, 0x38, 0xFF, 0x00, 0x10, 0x50, 0x6C, 0xFF, 0x85, 0x00, 0x00, 0x00,
0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x01, 0x16, 0x1D, 0x38, 0xFF, 0x10,
0x50, 0x6C, 0xFF, 0x81, 0x16, 0x1D, 0x38, 0xFF, 0x85, 0x00, 0x00, 0x00,
0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x83, 0x16, 0x1D, 0x38, 0xFF, 0x85,
0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x03, 0x16, 0x1D,
0x38, 0xFF, 0x10, 0x50, 0x6C, 0xFF, 0x16, 0x1D, 0x38, 0xFF, 0x10, 0x50,
0x6C, 0xFF, 0x85, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00,
0x89, 0x24, 0xBA, 0x24, 0xFF, 0x82, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00,
0x00, 0x00, 0x00, 0x87, 0x24, 0xBA, 0x24, 0xFF, 0x00, 0x1A, 0x87, 0x2F,
0xFF, 0x82, 0x24, 0xBA, 0x24, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x82, 0x24, 0xBA, 0x24, 0xFF, 0x00, 0x1A, 0x87,
0x2F, 0xFF, 0x81, 0x24, 0xBA, 0x24, 0xFF, 0x00, 0x1A, 0x87, 0x2F, 0xFF,
0x86, 0x24, 0xBA, 0x24, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x24,
0xBA, 0x24, 0xFF, 0x81, 0x24, 0xBA, 0x24, 0xFF, 0x00, 0x1A, 0x87, 0x2F,
0xFF, 0x86, 0x24, 0xBA, 0x24, 0xFF, 0x05, 0x1A, 0x87, 0x2F, 0xFF, 0x24,
0xBA, 0x24, 0xFF, 0x1A, 0x87, 0x2F, 0xFF, 0x24, 0xBA, 0x24, 0xFF, 0x1A,
0x87, 0x2F, 0xFF, 0x24, 0xBA, 0x24, 0xFF, 0x86, 0x24, 0xBA, 0x24, 0xFF,
0x00, 0x1A, 0x87, 0x2F, 0xFF, 0x87, 0x24, 0xBA, 0x24, 0xFF, 0x81, 0x24,
0xBA, 0x24, 0xFF, 0x02, 0x1A, 0x87, 0x2F, 0xFF, 0x24, 0xBA, 0x24, 0xFF,
0x1A, 0x87, 0x2F, 0xFF, 0x8A, 0x24, 0xBA, 0x24, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x88, 0x24, 0xBA, 0x24, 0xFF, 0x02, 0x1A, 0x87, 0x2F, 0xFF,
0x24, 0xBA, 0x24, 0xFF, 0x1A, 0x87, 0x2F, 0xFF, 0x81, 0x24, 0xBA, 0x24,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x84,
0x24, 0xBA, 0x24, 0xFF, 0x00, 0x1A, 0x87, 0x2F, 0xFF, 0x85, 0x24, 0xBA,
0x24, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00,
0x87, 0x24, 0xBA, 0x24, 0xFF, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x52, 0x55, 0x45, 0x56, 0x49,
0x53, 0x49, 0x4F, 0x4E, 0x2D, 0x58, 0x46, 0x49, 0x4C, 0x45, 0x2E, 0x00
};
void LoadTree( void )
{
glGenTextures( 1, &g_Texture );
glBindTexture( GL_TEXTURE_2D, g_Texture );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, treeData+18 );
}
//--------------------------------------------------------------------------------------------
// InitSDL()
//--------------------------------------------------------------------------------------------
void InitSDL( void )
{
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
exit( -1 );
atexit( SDL_Quit );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
SDL_DisplayMode currentDisplay;
SDL_GetCurrentDisplayMode( 0, &currentDisplay );
g_ScreenWidth = max( currentDisplay.w, currentDisplay.h );
g_ScreenHeight = min( currentDisplay.w, currentDisplay.h );
SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode( 0, &displayMode );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );
// PDS: GLES 2 will require shaders etc..
//SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 1 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
g_SDLWindow = SDL_CreateWindow( "Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
g_ScreenWidth,
g_ScreenHeight,
/* SDL_WINDOW_FULLSCFREEN | */ SDL_WINDOW_OPENGL );
if( g_SDLWindow == NULL )
exit( -1 );
SDL_GL_CreateContext( g_SDLWindow );
glViewport( 0, 0, g_ScreenWidth, g_ScreenHeight ); // Reset The Current Viewport
glMatrixMode( GL_PROJECTION ); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
glRotatef( -90, 0, 0, 1 );
glOrthof( 0.0f, g_ScreenWidth, g_ScreenHeight, 0.0f, -1.0f, 1.0f );
glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
glTranslatef(0.5, 0.5, 0);
glClearColor( 0.9f, 0.9f, 0.9f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
LoadTree();
glShadeModel(GL_SMOOTH);
}
float sq[] =
{
-7, 7, 0,
7, 7, 0,
-7, -7, 0,
7, -7, 0
};
float tri[] =
{
sq[ 0 ], sq[ 1 ], sq[ 2 ],
sq[ 3 ], sq[ 4 ], sq[ 5 ],
sq[ 6 ], sq[ 7 ], sq[ 8 ],
sq[ 6 ], sq[ 7 ], sq[ 8 ],
sq[ 3 ], sq[ 4 ], sq[ 5 ],
sq[ 9 ], sq[ 10], sq[ 11]
};
float texCoords[]=
{
0, 1,
1, 1,
0, 0,
0, 0,
1, 1,
1, 0
};
//--------------------------------------------------------------------------------------------
// Draw()
//--------------------------------------------------------------------------------------------
void Draw( int x, int y )
{
glEnable( GL_TEXTURE_2D );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glBindTexture( GL_TEXTURE_2D, g_Texture );
glPushMatrix();
glDisable( GL_BLEND );
glDisable( GL_CULL_FACE );
glEnable( GL_TEXTURE_2D );
GLfloat tX = (GLfloat) 10.0f;
GLfloat tY = (GLfloat) 10.0f;
GLfloat xOffset = 0;
GLfloat yOffset = 0;
// PDS: Offset the drawing by half character width since all placement will be done from quad centre..
xOffset = tX;
yOffset = tY;
glTranslatef( xOffset + x, yOffset + y, 0.0f);
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glFrontFace( GL_CW );
glVertexPointer( 3, GL_FLOAT, 0, tri );
glTexCoordPointer( 2, GL_FLOAT, 0, texCoords );
glDrawArrays( GL_TRIANGLES, 0, 6 );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glPopMatrix();
glBindTexture( GL_TEXTURE_2D, 0 );
glEnable( GL_BLEND );
}
//--------------------------------------------------------------------------------------------
// main()
//--------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
InitSDL();
SDL_Event event;
while( g_Running )
{
while( SDL_PollEvent( &event ) )
{
switch( event.type )
{
case SDL_QUIT:
g_Running = false;
break;
}
}
Draw( 100, 100 );
SDL_GL_SwapWindow( g_SDLWindow );
}
SDL_Quit();
return EXIT_SUCCESS;
}
I figured this out.. The ordering of setting the Projection and ModelView uniforms was wrong - it had to be done after the shader program was in use.. and I had some crazy vertice values for the triangles making up the destination rectangle.
The raw TGA loading didn't work very well either so I went back to my original code for loading TGA files.
The below link contains a working example.
Working Example

Bluetooth LE HID Eject Key Code?

I am implementing a dongle based on the TI Bluetooth LE HID sample that needs to restore or disable keyboard functionality. When using an Apple keyboard with an iOS device, pressing the eject button will enable/disable the device, hiding/showing the keyboard.
Most references say there is no key code for the eject button, although one lists it as 161; this does not work when used from a Bluetooth LE device. What are the key codes sent to the device from the keyboard to accomplish this?
I am assuming, of course, that a Bluetooth LE device will send the same key codes as a Bluetooth device, and that Apple's implementation of the Bluetooth LE HID includes the functionality for hiding and restoring the keyboard. If one of these assumptions is incorrect, that would help, too.
I've successfully gotten this working with an Nordic Semiconductor's nRF51822 and S110, using the following report map:
static uint8_t report_map_data[] =
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report Id (1)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0xe0, // Usage Minimum (224)
0x29, 0xe7, // Usage Maximum (231)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Constant) reserved byte(1)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (Page# for LEDs)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x91, 0x02, // Output (Data, Variable, Absolute), Led report
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output (Data, Variable, Absolute), Led report padding
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x65, // Logical Maximum (101)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0x00, // Usage Minimum (0)
0x29, 0x65, // Usage Maximum (101)
0x81, 0x00, // Input (Data, Array) Key array(6 bytes)
0x09, 0x05, // Usage (Vendor Defined)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Count (2)
0x95, 0x02, // Report Size (8 bit)
0xB1, 0x02, // Feature (Data, Variable, Absolute)
0xC0, // End Collection (Application)
// Report ID 2: Advanced buttons
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // Report Id (2)
0x15, 0x00, // Logical minimum (0)
0x25, 0x01, // Logical maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x0A, 0xAE, 0x01, // Usage (AL Keyboard Layout)
0x81, 0x06, // Input (Data,Value,Relative,Bit Field)
0xC0 // End Collection
};
Having this report map enables me to send a toggle with this:
static void toggle_send(void)
{
uint32_t err_code;
uint8_t release = 0;
uint8_t keyboard_toggle = 0x01;
// 1 designates the report index, not report ID.
err_code = ble_hids_inp_rep_send(&m_hids, 1, sizeof(keyboard_toggle), &keyboard_toggle);
APP_ERROR_CHECK(err_code);
err_code = ble_hids_inp_rep_send(&m_hids, 1, sizeof(release), &release);
APP_ERROR_CHECK(err_code);
}
I don't know the TI APIs in detail, but I hope this can be useful to refer to nevertheless. The above modifications should be easy to add to the ble_app_hids_keyboard in the regular nRF51 SDK, if you also have access to that chip.
this was worked for me:
static void hids_init(void)
{
ret_code_t err_code;
ble_hids_init_t hids_init_obj;
ble_hids_inp_rep_init_t * p_input_report;
ble_hids_outp_rep_init_t * p_output_report;
ble_hids_feature_rep_init_t * p_feature_report;
uint8_t hid_info_flags;
static ble_hids_inp_rep_init_t input_report_array[2];
static ble_hids_outp_rep_init_t output_report_array[1];
static ble_hids_feature_rep_init_t feature_report_array[1];
static uint8_t report_map_data[] =
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, 0x00, // Report Id (1)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0xe0, // Usage Minimum (224)
0x29, 0xe7, // Usage Maximum (231)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Constant) reserved byte(1)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (Page# for LEDs)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x91, 0x02, // Output (Data, Variable, Absolute), Led report
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output (Data, Variable, Absolute), Led report padding
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x65, // Logical Maximum (101)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0x00, // Usage Minimum (0)
0x29, 0x65, // Usage Maximum (101)
0x81, 0x00, // Input (Data, Array) Key array(6 bytes)
0x09, 0x05, // Usage (Vendor Defined)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Count (2)
0x95, 0x02, // Report Size (8 bit)
0xB1, 0x02, // Feature (Data, Variable, Absolute)
0xC0, // End Collection (Application)
// Report ID 2: Advanced buttons
0x05, 0x0C, // Usage Page (Consumer)
0x09, 0x01, // Usage (Consumer Control)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report Id (2)
0x15, 0x00, // Logical minimum (0)
0x25, 0x01, // Logical maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x0A, 0xAE, 0x01, // Usage (AL Keyboard Layout)
0x81, 0x06, // Input (Data,Value,Relative,Bit Field)
0xC0 // End Collection
};
memset((void *)input_report_array, 0, sizeof(ble_hids_inp_rep_init_t));
memset((void *)output_report_array, 0, sizeof(ble_hids_outp_rep_init_t));
memset((void *)feature_report_array, 0, sizeof(ble_hids_feature_rep_init_t));
// Initialize HID Service
p_input_report = &input_report_array[INPUT_REPORT_KEYS_INDEX];
p_input_report->max_len = INPUT_REPORT_KEYS_MAX_LEN;
p_input_report->rep_ref.report_id = INPUT_REP_REF_ID;
p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;
p_input_report->sec.cccd_wr = SEC_JUST_WORKS;
p_input_report->sec.wr = SEC_JUST_WORKS;
p_input_report->sec.rd = SEC_JUST_WORKS;
// Initialize HID Service
p_input_report = &input_report_array[1];
p_input_report->max_len = INPUT_REPORT_KEYS_MAX_LEN;
p_input_report->rep_ref.report_id = 1;
p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;
p_input_report->sec.cccd_wr = SEC_JUST_WORKS;
p_input_report->sec.wr = SEC_JUST_WORKS;
p_input_report->sec.rd = SEC_JUST_WORKS;
p_input_report = &input_report_array[INPUT_REPORT_KEYS_INDEX];
p_output_report = &output_report_array[OUTPUT_REPORT_INDEX];
p_output_report->max_len = OUTPUT_REPORT_MAX_LEN;
p_output_report->rep_ref.report_id = OUTPUT_REP_REF_ID;
p_output_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_OUTPUT;
p_output_report->sec.wr = SEC_JUST_WORKS;
p_output_report->sec.rd = SEC_JUST_WORKS;
p_feature_report = &feature_report_array[FEATURE_REPORT_INDEX];
p_feature_report->max_len = FEATURE_REPORT_MAX_LEN;
p_feature_report->rep_ref.report_id = FEATURE_REP_REF_ID;
p_feature_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_FEATURE;
p_feature_report->sec.rd = SEC_JUST_WORKS;
p_feature_report->sec.wr = SEC_JUST_WORKS;
hid_info_flags = HID_INFO_FLAG_REMOTE_WAKE_MSK | HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK;
memset(&hids_init_obj, 0, sizeof(hids_init_obj));
hids_init_obj.evt_handler = on_hids_evt;
hids_init_obj.error_handler = service_error_handler;
hids_init_obj.is_kb = true;
hids_init_obj.is_mouse = false;
hids_init_obj.inp_rep_count = 2;
hids_init_obj.p_inp_rep_array = input_report_array;
hids_init_obj.outp_rep_count = 1;
hids_init_obj.p_outp_rep_array = output_report_array;
hids_init_obj.feature_rep_count = 1;
hids_init_obj.p_feature_rep_array = feature_report_array;
hids_init_obj.rep_map.data_len = sizeof(report_map_data);
hids_init_obj.rep_map.p_data = report_map_data;
hids_init_obj.hid_information.bcd_hid = BASE_USB_HID_SPEC_VERSION;
hids_init_obj.hid_information.b_country_code = 0;
hids_init_obj.hid_information.flags = hid_info_flags;
hids_init_obj.included_services_count = 0;
hids_init_obj.p_included_services_array = NULL;
hids_init_obj.rep_map.rd_sec = SEC_JUST_WORKS;
hids_init_obj.hid_information.rd_sec = SEC_JUST_WORKS;
hids_init_obj.boot_kb_inp_rep_sec.cccd_wr = SEC_JUST_WORKS;
hids_init_obj.boot_kb_inp_rep_sec.rd = SEC_JUST_WORKS;
hids_init_obj.boot_kb_outp_rep_sec.rd = SEC_JUST_WORKS;
hids_init_obj.boot_kb_outp_rep_sec.wr = SEC_JUST_WORKS;
hids_init_obj.protocol_mode_rd_sec = SEC_JUST_WORKS;
hids_init_obj.protocol_mode_wr_sec = SEC_JUST_WORKS;
hids_init_obj.ctrl_point_wr_sec = SEC_JUST_WORKS;
err_code = ble_hids_init(&m_hids, &hids_init_obj);
APP_ERROR_CHECK(err_code);
}

Resources