getting OS and language over serial (Pro Micro)

Hello, i am trying to get my Ardunio Pro Micro to detect a system language and then convert its ASCII values to match.
I am trying to find a way to get the Ardunio to ask for the OS and its language.

As far as i can tell the current keyboard library (hardware\arduino\avr\cores\arduino\HID.cpp) only supports one key layout. (or im missing something)
Basically i have an issue where i am sending an email through serial to the Ardunio then through serial to a windows PC. The Ardunio receives a @ symbol however the PC receives a " symbol

//Default HID lib
    0x1f,          // 2
    0x1f|SHIFT,	   // "
    0x34,          // '
    0x34|SHIFT,      // @


//EN-GB ASCII codes
    0x34,          // '
    0x34|SHIFT,	   // "
    0x1f,          // 2
    0x1f|SHIFT,      // @

I just though it might be simpler rather then editing the code all the time for new languages (i want to support as many as possible), i would just try modify the existing HID.cpp lib and use the ASCII codes as a variable depending on what language the connected computer is (mac, Windows, Linux).

Would i have to build a small app that will get the OS language settings and then send them over serial to the Ardunio or is there a way i can get the Ardunio to ask for them.

Why are you sending an email as a series of keystrokes rather than as text using Serial.print().

...R

How is this going to find the language of the OS?

Computers use unicode I think. Haven't been ASCII for a while. You're not going to see Chinese using ASCII lol.

Sorry i should specify im not using Serial.print as I'm making a keyboard type device, so im using Keybaord.print() which sends the string by ASCII characters.

What im wanting to do:

  1. Create a library of Keyboard layouts for different languages.
  2. Get OS system language via USB serial
  3. Define which Language to use in the HID.cpp code from the library

Creating and defining the library is something i can do after a better look into c++ (im still a noob at it). its just getting the system language which is the problem.

I know windows has a c++ function to get the system language as a hex value. ("GetSystemDefaultUILanguage();")
not sure about it on mac yet but that can come in later when i can get access to the mac at work.

What I don't understand is how you will get the PC to call GetSystemDefaultUILanguage() without you writing a special program on the PC to do that ?

And if you need a special program on the PC you won't be automatically detecting the language.

...R

This is what im asking about. I know windows has that function, I am wanting to know if i get get the Ardunio that infomation across as part of its setup script.
really bad example:

void setup {
    Serial.being(9600);
    langid = Serial.GET(GetSystemDefaulyUILanguage())
    preflangid = (langid or set langiage option here)
    Serial.print(langid);
    Keyboard.being(langid, pref langid)
 // this will not work!
}

void loop {
 Keyboard.print("hello")
}

so basically, on setup the Ardunio will ask for the windows language id.
From there you can set a specific language if you want (optional). Then in the keyboard.begin code it accepts the OS language and the language the user wants to use.
the 2 options for language is so a user who is on a French computer can sill use a English key layout if they want.
But like i said im not sure on how much of this is possible, im just testing the waters and trying to get some ideas on what people have tried and what other people think it should do etc.

AceScottie:
langid = Serial.GET(GetSystemDefaulyUILanguage())

This is just not possible.

An Arduino cannot call functions on a PC whether it is running Windows, or Linux or Mac.

You need to have a program running on the PC (perhaps written in Python because it works on the different operating systems). That program will listen for a request from the Arduino, it will than ask the PC what language it is using and send the answer to the Arduino.

And it is probably not even that simple, because someone will have to tell the PC program which serial port the Arduino is connected to.

...R

Thanks thats a pretty good idea to follow from.
So far iv determined my os language is wrong ... (everything is in en_us rather than en_gb even though all my language settings were set on install ...)

I found the correct packs to run windows functions from python and made some small code:

import os
import time
import ctypes
windll = ctypes.windll.kernel32
lang = windll.GetUserDefaultUILanguage()
print(lang)

Im still working out macs like i said before.

As for sending it one serial...
Windows actually list the Ardunio in device manager under something like "Ardunio Pro Micro COM4"
learnt that from a bug where it listed every COM port as availbe for write on the Ardunio program editor.

I am looking for another windows code that can scan the device manager and look for the name Ardunio ***** COM*
and use that to figure out what port its on.

Ok little more code for this. (i am going to be updating this thread whenever i find something new)

import os
import time
import ctypes
import wmi
windll = ctypes.windll.kernel32
lang = windll.GetUserDefaultUILanguage()
print(lang)
Ardport = "not found"
c = wmi.WMI()
wql = "Select * From Win32_USBControllerDevice"
for item in c.query(wql):
        s = str(item.Dependent.Caption)
        strfind = "Ardunio"
#      print (s)
        if (s.find(strfind) >= 0):
                Ardport = item.Dependent.Caption
print (Ardport)

this code will print your langid (in my case was 1033) and a device from a list of devices.
I dont have my Ardunio on me and wont have till monday (left it at work), so if anyone can have a check of this for me and see if Ardunio gets listed.

example print

>>>1103
>>>Ardunio Pro Micro COM4

if the Ardunio is not listed it will print "not found", if that happenes un # print(s) and see if it comes up in the list of devices.

Code requires Modual wmi WMI · PyPI

So far iv determined my os language is wrong

Must be Windows... 8)

Yea whats funny is all the regional and location settings are set to English UK (en_gb) however the registry and language pack is set to English US (en-us)...

If anyone can get together some ACII configs for French, German and Spanish languages I can start work on putting those into a library and Defining them in the HID.cpp

Also started working on a driver app (backgroudn app for windows) to run the python.
I think the way ill work it is like my graphics tablet.

In the python it will wait for anything called Ardunio to show up on the device list.
If it finds something it will get the port and print language to that port.
on the Ardunio setup loop it will wait for a response from the PC, (response being the language).
Once it loads the language it will keep that as a variable and when defining keybaord.begin() wil add the language in the ()
keybaord.begin(en_gb)

You may be interested in this Python GUI demo. I wrote it on Linux and I think others have tried it successfully on Windows and Mac.

It has code to allow the user to select the serial port.

...R

Thanks that will help a bunch, right now i don't have my Ardunio with me so cant start testing it yet.
I'm currently working on getting the python code to run as a background process in windows (which windows doesn't like) problem is the list of modules needed keeps increasing ...

I'm not familiar with installers but is it possible to execute multiple silent installers for each of the modules ? or can i just pack up all the files from the modules and extract them to the python directory on install ?
not sure about redistribution rights for python modules ...

AceScottie:
I'm not familiar with installers but is it possible to execute multiple silent installers for each of the modules ? or can i just pack up all the files from the modules and extract them to the python directory on install ?

I certainly don't claim to be a Python expert. In my experience any of the Python libraries I have tried (PySerial, Bottle, Peewee) can be stored within the directory of my Python project without any need for a formal instal process.

I much prefer to have all the libraries in my project so there are no external dependencies and no confusion about versions if I want to take the project to another PC. This does mean some extra disk space is used but the cost is trivial.

...R

a lot of struggling later. i got the code working (ish) will break if you change USB devices on the system so wouldnt recommend having a flash drive in atm. (work on a fix)

new code as follows
test.py:

# -*- coding: utf-8 -*-

import time
import thread
import os
import serial
import sys
import ctypes
import wmi
from langpy import lang
from langpy import port
import pythoncom




class service_test:
    def __init__(self):
            thread.start_new(self.check_for_Ardunio, tuple())

    def check_for_Ardunio(self):
            r1 = ""
            comp = ""
            reply = ""
            j1 = -1
            while True:
                    plang = (str(lang()))
                    pport = (str(port()))
                    if (pport != ""):
                            j1 = pport[-2:-1]
                            comp = ('COM' + j1)
                            if (reply != "reply" and j1 >= 0):
                                    ser = serial.Serial(comp, 9600, timeout=1)
                                    if(ser.isOpen()):
                                        ser.close()
                                    ser.open()
                                    ser.write(plang)
                                    time.sleep(0.5)
                                    while (ser.inWaiting()):
                                        char = ser.read()
                                        r1 += char
                                        time.sleep(0.02)
                                      

                                    if (len(r1) >0):
                                        reply = r1
                                        r1 = ""
                                    
                                    ser.close()
                                    print ("sent message")
                                
                    else:
                            time.sleep(1)
                            reply = ""
                            j1 = -1
                            comp = 'COM'
            #DEBUGGING
                    print(comp)
                    print(plang)
                    print(pport)
                    print (j1)
                    print (str(reply)) 
                    print ("")

if __name__ == "__main__":
        tst = service_test()

langpy.py

import os
import time
import ctypes
import wmi
import thread
import pythoncom
import locale

def lang():
    localelang = locale.getdefaultlocale()
    language = str(localelang)[2:7]
    #print (language)
    return language

def port():
                pythoncom.CoInitialize()
                Ardport = ""
                c = wmi.WMI()
                wql = "Select * From Win32_USBControllerDevice"
                for item in c.query(wql):
                                s = str(item.Dependent.Caption)
                                #print (item.Dependent.Caption)
                                strfind = "Arduino"
                                strignore = "bootloader"
                                if (s.find(strfind) >= 0 and s.find(strignore) == -1):
                                        Ardport = item.Dependent.Caption
                time.sleep(1)
                return Ardport

Ardunio code:

String readString;
String readString2;
void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  Keyboard.begin();
 }
void loop() {
  
    while (Serial.available()) {
    char x = Serial.read();
    readString2 += x;
    delay(2);  
  }

  if (readString2.length() >0) {
    lang = readString2;
    Serial.print("reply"); 
    readString2 = "";
  }
  

  while (Serial1.available()) {
    char c = Serial1.read();
    readString += c;
    delay(2);  
  }

  if (readString.length() >0) {
    Serial.println(readString); 
    Keyboard.print(readString);
    readString="";
  } 
}

now i just need to take then "lang" variable and set it as the language to use on the Ardunio.