Base64 kódoló könyvtár Arduino-val
Bázis64 egy olyan kódrendszer, amely 64 szimbólumot használ üzenetekbe csoportosítva, amelyek hossza négyes többszöröse. Ezeket az üzeneteket (adatcsomagokat) szükség esetén pluszjellel (tehát 65-öt használunk), gyakran egyenlőségjellel (=) egészítjük ki, ha a kódolt hasznos információ rövidebb hosszúságot eredményez.
64 jellel dolgozhat a kód 10 számával és kis- és nagybetűivel (26+26) ASCII, az a probléma, hogy van 62, mondjuk, egyértelmű szimbólum plusz kettő, amelyek a különböző megvalósításokban változnak. Bár néha a „karakterek” kifejezéssel hivatkoznak rájuk ASCII nyomtatható", a valóságban ezek azok, amelyek a 32-es kódtól (szóköz) a 126-ig (~) a valóban nyomtatható 95-ig terjednek.
A kódolás megvalósítása Bázis64 leggyakrabban használt, hogy a PEM, amelyet szintén használ PANTOMIM, dolgozzon a plusz "+" és "/" jelekkel, valamint az "=" jellel a padokhoz, hogy a csomagok hossza négyes többszöröse legyen. Az A-Z betűk 0-25, az a-z betűk a 26-51, a 0-9 számok az 52-61, a pluszjel (+) a 62, a 63 pedig a perjel (/ ) foglalja el.
Az adatok formátumban történő megjelenítésének módja Bázis64 abból áll, hogy az eredeti adatokból csoportokat veszünk 6 bit amelyeket a megfelelő kóddal ábrázolunk. Ha bitek maradnak, jobbra nullákkal töltik fel. Ha a kapott kódszám nem négyszerese, akkor egyenlőségjelekkel töltjük ki jobbra.
A következő képen a kódolás látható ASCII szöveg ("ohm") és a konvertálás módja Bázis64. Mivel 7 szimbólum van, az utolsó üzenetet egyenlőségjellel kell kitölteni a végén. Azt lehetne mondani, hogy az "ohm" szöveg be ASCII egyenértékű a «b2htaW8=" in Bázis64.
A kódolás speciális felhasználási módjai Bázis64 Általában megszabnak egy maximális vonalhosszt is. Az implementáció PANTOMIM Az egyes sorokat 76 karakterre korlátozza. Általában a sorokat egy sorvégi kód választja el (CR, amelyet a 0x0D érték képvisel ASCII) és egy másik új sor (NL, amely megfelel a kódnak ASCII 0x0A).
A kódolás végrehajtása során felmerülő kényelmetlenség Bázis64 kevés erőforrással rendelkező eszközön, ahogy az gyakran előfordul a mikrovezérlő az, hogy kódolnia kell az információ beérkezésekor vagy a ütköző minimum, amihez szükség van egy olyan rendszer biztosítására is, amely jelzi, hogy az eredeti üzenet végét elérték, például egy speciális kód hozzáadásával, vagy olyan PIN-kód használatával, amelynek szintje (a vétellel szinkronizálva) jelzi az üzenet állapotát.
Az alábbi példakód a könyvtár az Arduino számára a Base64 kódolásához amely mindkét feltétellel valósul meg: a beérkező információ kódolása (a nélkül ütköző), és várja meg a figyelmeztető jelzés befejezését.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//base64.h
#include <string.h> // memcpy/strncpy
#define LONGITUD_LINEA 76
#define MASCARA_B64 0B00111111
#define ULTIMO_CODIGO_BASE64 64 // 64 caracteres más el signo igual (empezando a contar desde cero)
#define MAXIMA_LONGITUD_RESULTADO 6 // Máximo número de caracteres del resultado parcial de la codificación. Puede ser 1 si no se ha llegado al final de un bloque (2 bytes en el original, 4 en la conversión), 2 si se ha llegado al final de un bloque, 3 si no se ha llegado al final de un bloque pero se supera la longitud máxima de la línea, 4 si se llega al final de un bloque y se supera la longitud máxima de la línea, 5 si hay que rellenar con un signo igual o 6 si hay que rellenar con dos signos igual
class Base64
{
private:
unsigned char simbolo_base64[ULTIMO_CODIGO_BASE64+1]; // Espacio para la codificación Base64, el relleno (=) una terminación en \0
unsigned int numero_valor; // Posición (empezando en cero) que ocupa el valor que se desea convertir en el mensaje completo original
unsigned int numero_codigo; // Posición del último código calculado. Podría limitarse al ancho de la línea (LONGITUD_LINEA, 76 caracteres) pero usando un contenedor alto se podría implementar también una cuenta estadística
unsigned char resto_base64; // Último resto obtenido al calcular el último código
unsigned char resultado[MAXIMA_LONGITUD_RESULTADO+1]; // Resultado de la conversión actual. Si es terminal puede incluir el caracter 65 (=) una o dos veces
unsigned char contador_caracteres_resultado=0;
void acumular_resultado(unsigned char valor);
public:
Base64();
~Base64();
void iniciar_conversion();
unsigned char *convertir(unsigned char valor_original, bool terminar_conversion);
unsigned char *convertir(unsigned char valor_original);
unsigned char *terminar();
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
//base64.cpp
#include “base64.h”
Base64::Base64() // Constructor
{
memcpy(simbolo_base64,“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=”,ULTIMO_CODIGO_BASE64+1);
iniciar_conversion();
}
Base64::~Base64() // Destructor
{
}
void Base64::iniciar_conversion()
{
numero_valor=0;
numero_codigo=0;
resto_base64=0;
}
unsigned char *Base64::convertir(unsigned char valor_original, bool terminar_conversion) // Valor que se desea convertir a Base64
{
convertir(valor_original);
if(terminar_conversion)
{
terminar();
}
return resultado;
}
unsigned char *Base64::convertir(unsigned char valor_original) // Valor que se desea convertir a Base64
{
unsigned char desplazamiento;
contador_caracteres_resultado=0;
acumular_resultado((valor_original>>(2+(numero_valor%3)*2))|resto_base64);
desplazamiento=4–(numero_valor%3)*2;
resto_base64=(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento;
if(((numero_codigo+1)%4==0))
{
acumular_resultado(resto_base64);
resto_base64=0;
}
numero_valor++;
resultado[contador_caracteres_resultado]=0;
return resultado;
}
unsigned char *Base64::terminar()
{
if(numero_codigo%4)
{
acumular_resultado(resto_base64);
while(numero_codigo%4)
{
acumular_resultado(ULTIMO_CODIGO_BASE64);
}
}
resultado[contador_caracteres_resultado]=0;
iniciar_conversion();
return resultado;
}
void Base64::acumular_resultado(unsigned char valor)
{
numero_codigo++;
resultado[contador_caracteres_resultado++]=simbolo_base64[valor];
if((numero_codigo%LONGITUD_LINEA)==0)
{
resultado[contador_caracteres_resultado++]=13; // CR “\r”
resultado[contador_caracteres_resultado++]=10; // LF “\n”
}
}
|
A kódszámítás alapvető része Bázis64 Ez a következő kifejezéssel történik:
(valor_original>>(2+(numero_valor%3)*2))|resto_base64
és a maradék kiszámítása a következő kifejezéssel:
(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento
,
lét desplazamiento
a következő kifejezéssel kiszámított érték:
4-(numero_valor%3)*2
A kifejezések megszerzéséhez követett eljárás a négy kód mindegyikének kiszámításának általánosításából áll Bázis64 amelyek az eredeti érték három bájtjának megjelenítéséből származnak.
Base64=((byte_1>>2)|resto)&0b00111111 |
resto=(byte_1&0b00000011)<<4 |
Base64=((byte_2>>4)|resto)&0b00111111 |
resto=(byte_2&0b00001111)<<2 |
Base64=((byte_3>>6)|resto)&0b00111111 |
resto=(byte_3&0b00111111)<<0 |
Base64=((byte_3>>0)|resto)&0b00111111 |
resto=(byte_3&0b00111111)<<0 |
A szöveggel Base64
A fenti pszeudokód a bemeneti kódra vonatkozik Bázis64 ami számítás alatt van. A kifejezést használták byte_n
a kódolt n-edik bájtra utalni. A szöveg resto
a kódolt bájt maradék bitjeit jelöli. A számítás elején feltételezzük, hogy a maradék nulla
Az áttekinthetőség kedvéért az előző pszeudokódban a 6 bites maszk minden kód számításába bekerült, bár ezek közül csak az utolsót kell meghatározni, mivel a többi úgy van elforgatva, hogy mindig a két legtöbb bit elveszik. jelentős.
Mint látható, a negyedik kód csak maradék, és nincs szükség a maradék kiszámítására. Ezért csak három lépést kell végrehajtani, kódolt bájtonként egyet. Fontos megjegyezni, hogy ha egy csomag harmadik bájtja nincs kódolva, akkor az utolsó kódot nullákkal kell kitölteni a jobb oldalon. Bázis64 kapott.
Általánosságban a kódot kiszámító kifejezés megfelelő elforgatása Bázis64 ként ábrázolható 2+(numero_byte%3)*2
hogy a zárójelben lévő rész nulláról kettőre forogjon, így minden lépésben 2, 4 és 6 lesz. Természetesen nem ez az egyetlen módja az általánosításnak, de a funkcionalitás és mindenekelőtt az áttekinthetőség miatt választottam ezt. Mivel a maszk (ÉS) csak a negyedik kódban volt szükséges, és már láttuk, hogy nem kell kiszámítani (ez mind a maradék), ezért nem szerepel a végső kifejezésben az egyszerűsítés érdekében, bár emlékeznünk kell hogy a felhasznált adattípus (byte ) csak a 6 legkisebb jelentőségű bitet veszik fel.
A többi balra forgatása az előzőhöz hasonló módon általánosítható. Az is látható, hogy az alkalmazott maszk (ÉS) ugyanazon a bitforgatáson megy keresztül, de ellenkező irányban. Ez az oka az elmozdulás kiszámításának 4-(numero_valor%3)*2
mielőtt a kifejezés egyes részeinek megfelelő értelemben alkalmazná.
A következő példa bemutatja, hogyan használhatja a könyvtárat egy szöveges karakterlánc kódolására (ne feledje Bázis64 bármilyen adatkészlethez, például képhez használható). A következő kódban van néhány részlet, amelyeket érdemes tisztázni. Először is, egy speciális szimbólumot (a ~ szimbólumot) használtak a szöveg végének jelzésére, a hardveres jel vagy a szöveg hosszának jelzése helyett. Logikailag ez a szimbólum nem lehet része a kódolt adatoknak.
A második kérdés, amelyet figyelembe kell venni, amennyire nyilvánvaló, az az, hogy a célállomás dekóderének tudnia kell, hogy a hozzá eljutó információ hogyan jelenik meg. A szöveg olyan karaktereket tartalmaz, amelyek nem tartoznak a készlethez ASCII nyomtatható (32-126), például ékezetes betűk. Arduino két bájtot fog használni (UTF-8) jelképezi ezeket a karaktereket. A szokásosat nem lehet egyszerűen használni \0
szöveglezáróként, mivel sok esetben az első bájt, amellyel egy karaktert ábrázol, pontosan nulla lesz.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include “base64.h”
char texto_prueba[]=“La bella y graciosa moza marchose a lavar la ropa.\nLa mojó en el arroyuelo y cantando la lavó.\nLa frotó sobre una piedra, la colgó de un abedul.\nDespués de lavar la ropa, la niña se fue al mercado.\nUn pastor vendía ovejas pregonando a viva voz:\nved qué oveja, ved qué lana, ved qué bestia, qué animal.\nLa niña la vio muy flaca, sin embargo le gustó.\nYo te pago veinte escudos y no discutamos más.\nVuelve la niña cantando muy contenta con su oveja.\nCuando llegaron al bosque la ovejita se escapó.\nLa niña desesperada arrojose encima de ella.\nVelozmente y con destreza aferrola por detrás.\nLlegaba por el camino jinete de altivo porte.\nDescendió de su caballo y a la niña le cantó…~”;
char *resultado;
Base64 base64;
void setup()
{
Serial.begin(9600);
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // ¿Es un Arduino Leonardo (ATmega32U4)?
while(!Serial){}; // Esperar a Arduino Leonardo
#endif
// Mostrar el texto original
unsigned int contador=0;
while(texto_prueba[contador]!=‘~’)
{
//Serial.println(String(texto_prueba[contador])+”=”+String(texto_prueba[contador],DEC));
Serial.print(String(texto_prueba[contador]));
contador++;
}
Serial.println(“\n”);
// Mostrar el texto codificado en Base64
contador=0;
while(texto_prueba[contador]!=‘~’)
{
resultado=base64.convertir(texto_prueba[contador],texto_prueba[contador+1]==‘~’);
byte contador_resultado=0;
while(resultado[contador_resultado]>0)
{
Serial.print(String(resultado[contador_resultado]));
contador_resultado++;
}
contador++;
}
}
void loop()
{
}
|
Az előző példa 26. sora a használatát mutatja be könyvtár az Arduino számára a Base64 kódolásához. Csak a módszert kell feltüntetni convertir
minden kódolni kívánt bájt és opcionálisan az utolsó, vagy ha nem, állítsa le a konvertálást a metódussal terminar
amikor a végére érsz.
Amint az alábbi képernyőképen látható, a példaprogram a könyvtár az Arduino számára a Base64 kódolásához először megjeleníti a kódolandó szöveget Bázis64, jelen esetben az óriások híres dalának kezdete Les Luthiers, és ezt követően a kódolás eredménye Bázis64 sorhossz formátum használatával PANTOMIM.
Hozzászólás Comment