GSM modem AT commands UCS2 error 500 - php

Three days ago I started making a simple app to send SMS. I already tested it and it works in GSM CSCS mode, but when I switch it to UCS2 it doesn't show the Cyrillic letters
<?php
error_reporting(E_ALL);
$fp = fopen("/dev/ttyUSB0", 'w+');
$msg = strtoupper(bin2hex(mb_convert_encoding("Тест", "UCS-2", "UTF-8")));
$number_raw = "+359000000000";
$number = bin2hex(mb_convert_encoding($number_raw, "UCS-2", "UTF-8"));
echo $number."<br>";
echo $msg;
$debug = false;
if(!$fp || $debug){
//echo "Can not open!";
}else{
fwrite($fp, "AT+CMGF=1".chr(13)); // OK
sleep(5);
fwrite($fp, 'AT+CSCS="UCS2"'.chr(13)); // OK
sleep(5);
fwrite($fp, 'AT+CMGS="'.$number.'"'.chr(13)); // OK
sleep(5);
fwrite($fp, $msg.chr(26)); // ERROR 500
echo "<br>Sent";
}
?>
Number and message are encoded properly according to this source: http://www.columbia.edu/kermit/ucs2.html
When the message is sent, I receive it (so the encoding of the number is correct) but the content isn't shown properly.
https://imgur.com/a/cCaTU
What are possible causes for this behaviour and could it be my PHP file encoding? Also why is linux finding 3 GSM tty devices?

After you have removed all the horrible sleep calls and implemented proper final response parsing, then you need fix the parsing for waiting for the "\r\n> " response of AT+CMGS.
Without any of that fixed, character set encoding trouble is a very minor problem. When you run AT+CSCS="UCS2" every single string will be encoded by the modem that way and must be encoded that way by you until eternity (or another character set is selected), so for instance to switch from UCS2 to UTF-8 would be AT+CSCS="005500540046002D0038" and not AT+CSCS="UTF-8".

Related

Why would 00 in data break UTF-16 encode / OpenSSL?

I'm working on a PHP login that takes an ID and logs them in elsewhere after the user is already authenticated. It works for every single ID except three of them, and they all have something in common: They all start with two zeros (e.g.: 0012).
I'm wondering if a double zero holds a special place in the encoding, like a delimiter? Or something to do with OpenSSL? It only breaks on those three. Doesn't matter if I treat the data as a string or an integer, it breaks both ways. Any ideas?
Code (modified slightly):
$fp = fopen("/OpenSSL-Win64/bin/myrsakey.pem", "r");
$priv_key = fread($fp, 8192) or die("File not found.");
fclose($fp);
$pkeyid = openssl_get_privatekey($priv_key);
$data = '0012'; // THIS DOESN'T WORK
$data = '0123'; // THIS DOES WORK
$data = '1234'; // THIS ALSO WORKS
$data = mb_convert_encoding($data, "UTF-16LE");
openssl_sign($data, $signature, $pkeyid, OPENSSL_ALGO_SHA1);
openssl_free_key($pkeyid);
Why would 00 in data break UTF-16 encode / OpenSSL?
The problem is not with OpenSSL. OpenSSL just works with data - it does not care about encodings. It might be related to openssl_sign. But its hard to tell at the moment.
Your problem is likely related to mb_convert_encoding. However, you never stated what the actual problem was.
How does it not work? Does it not work when verifying the signature on a Linux system? Did you check for the presence (or absence) of a Byte Order Mark (BOM)? That's a real problem, especially when working with Java.

Send SMS containing 'æøå' with AT commands

I'm making a SMS sending function for at project i'm working on. The code works just fine, but
when i send the letters 'æ-ø-å-Æ-Ø-Å' it turns to 'f-x-e-F-X-E'.
How do i change the encoding so that I can send these letters?
This is my code:
<?php
include "php_serial.class.php";
$html = $_POST['msg'];
$serial = new phpSerial;
$serial->deviceSet("/dev/cu.HUAWEIMobile-Modem");
$serial->deviceOpen();
$serial->sendMessage("ATZ\n\r");
// Wait and read from the port
var_dump($serial -> readPort());
$serial->sendMessage("ATE0\n\r");
// Wait and read from the port
var_dump($serial -> readPort());
// To write into
$serial->sendMessage("AT+cmgf=1;+cnmi=2,1,0,1,0\n\r");//
$serial->sendMessage("AT+cmgs=\"+45{$_POST['number']}\"\n\r");
$serial->sendMessage("{$html}\n\r");
$serial->sendMessage(chr(26));
//wait for modem to send message
sleep(3);
$read=$serial->readPort();
$serial->deviceClose();
$read = preg_replace('/\s+/', '', $read);
$read = substr($read, -2);
if($read == "OK") {
header("location: index.php?send=1");
} else {
header("location: index.php?send=2");
}
?>
First of all, you must seriously redo your AT command handling to
Read and parse the every single response line given back from the modem until you get a final result code for every single command line invocation, no exceptions whatsoever. See this answer for more details.
For AT+CMGS specifically you also MUST wait for the "\n\r> " response before sending data, see this answer for more details.
Now to answer your question about æøå turning into fxe, this is a classical stripping of the most significant bit of ISO 8859-1 encoding (which I had almost forgotten about). This is probably caused the default character encoding, but since you always should be explicit and set the character encoding you want to use in any case, investigating that further is of no value. The character encoding used for strings to AT commands is controlled by the AT+CSCS command (see this answer for more details), run AT+CSCS=? to get a list of options.
Based on your information you seem to using ISO 8859-1, so running AT+CSCS="8859-1" will stop zeroing the MSB. You might be satisfied with just that, but I strongly recommend using character encoding UTF-8 instead, it is just so vastly superior to 8859-1.
All of that failing I am quite sure that at least one of the GMS or IRA encodings should supports the æøå characters, but then you have to do some very custom translation, those characters will have binary values very different from what is common in text elsewhere.

PHP & Android - UTF-8 encoding problems

We're doing a POST request via Android to PHP and Android is passing UTF-8 string, our database is currently cp1252 (has a live iPhone backend, hence working with it)
However we can't seem to get the string converted to cp1252. Tried the following code without results
$userkey = utf8_decode($userkey);
$userkey = iconv('UTF-8', 'cp1252', $userkey);
$userkey = mb_convert_encoding($userkey, 'cp1252', 'UTF-8');
Check the response with
echo 'userkey: '.mb_detect_encoding($userkey);
Always returns UTF-8
Further more if $userkey is sent with value "no" and we do the following
if($userkey == "no"){
echo "not registered"
}else{
echo "registered find db record"
}
The code always seems to drop into else - Any help would be great :)

Getting started on FIX protocol with PHP sockets

I have pretty basic knowledge of PHP sockets and the FIX protocol altogether. I have an account that allows me to connect to a server and retrieve currency prices.
I adapted this code to connect and figure out what I receive back from the remote server:
$host = "the-server.com";
$port = "2xxxx";
$fixv = "8=FIX.4.2";
$clid = "client-name";
$tid = "target-name";
$fp = fsockopen($host, $port, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "$fixv|9=70|35=A|49=$clid|56=$tid|34=1|52=20000426-12:05:06|98=0|108=30|10=185|";
echo "\n".$out."\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo ".";
echo fgets($fp, 1024);
}
fclose($fp);
}
and I get nothing back. The host is good because I'm getting an error when I use a random one.
Is the message I'm sending not generating a reply ?
I might not be very good at finding things in Google but I could not find any simple tutorial on how to do this with php (at least nothing that puts together fix and php).
Any help is greatly appreciated.
FIX separator character is actually '\001' not '|', so you have to replace that when sending.
Some links for you:
FIX protocol - formal specs
Onixs FIX dictionary - very useful site for tag lookup
Edit 0:
From that same wikipedia article you mention:
The message fields are delimited using the ASCII 01 character.
...
Example of a FIX message : Execution Report (Pipe character is used to represent SOH character) ...
Edit 1:
Couple more points:
Tag 9 holds message length without tags 8 (type), 9 (length), and 10 (checksum).
Tag 10, checksum, has to be a modulo 256 sum of ASCII values of all message characters including all SOH separators, but not including the tag 10 itself (I know, it's stupid to have checksums on top of TCP, but ...)
The issue is the use of fgets(...), it is expecting a \n which does not exists in this FIX protocol.
On top of that, an expected length of 1024 is specified, which is a length that the response is unlikely to exceed.
To cap it off, since the server doesn't terminate the connection, fgets(...) hangs there "forever"

PHP fputcsv with UTF-8 Problem

I'm trying to allow my clients view some of the MySQL data in Excel. I have used PHP's fputcsv() function, like:
public function generate() {
setlocale(LC_ALL, 'ko_KR.UTF8');
$this->filename = date("YmdHis");
$create = $this->directory."Report".$this->filename.".csv";
$f = fopen("$create","w") or die("can't open file");
fwrite($f, "\xEF\xBB\xBF");
$i = 1;
$length = count($this->inputarray[0]);
fwrite($f, $this->headers."\n");
// print column titles
foreach($this->inputarray[0] as $key=>$value) {
$delimiter = ($i == $length) ? "\n\n" : ",";
fwrite($f, $key.$delimiter);
$i++;
}
// print actual rows
foreach($this->inputarray as $row) {
fputcsv($f, $row);
}
fclose($f);
}
My clients are Korean, and a good chunk of the MySQL database contains values in utf8_unicode_ci. By using the above function, I successfully generated a CSV file with correctly encoded data that opens fine in Excel on my machine (Win7 in English), but when I opened the file in Excel on the client computer (Win7 in Korean), the characters were broken again. I tried taking the header (\xEF\xBB\xBF) out, and commenting out the setlocale, to no avail.
Can you help me figure this out?
If, as you say, your CSV file has "correctly encoded data" - i.e. that it contains a valid UTF-8 byte stream, and assuming that the byte stream of the file on your client's site is the same (e.g. has not been corrupted in transit by a file transfer problem) then it sounds like the issue Excel on the client's machine not correctly interpreting the UTF-8. This might be because it's not supported or that some option needs to be selected when importing to indicate the encoding. As such, you might try producing your file in a different encoding (using mb_convert_encoding or iconv).
If you get your client to export a CSV containing Korean characters then you'll be able to take a look at that file and determine the encoding that is being produced. You should then try using that encoding.
Try encoding the data as UTF-16LE, and ensure that the file has the appropriate BOM.
Alternatively, send your clients an Excel file rather than a CSV, then the encoding shouldn't be a problem
Try wrapping the text in each fwrite call with utf8_encode.
Then use what is suggested here: http://www.php.net/manual/en/function.fwrite.php#69566

Categories