Knjižnica za kodiranje Base64 z Arduinom
Baza64 je sistem kodiranja, ki uporablja 64 simbolov, združenih v sporočila, katerih dolžina je večkratnik štiri. Ta sporočila (podatkovni paketi) se po potrebi zaključijo s simbolom plus (zato se uporablja 65), pogosto z znakom enačaja (=), če so kodirane koristne informacije krajše.
Z uporabo 64 znakov lahko delate z 10 številkami ter velikimi in malimi črkami (26+26) kode ASCII, je težava v tem, da obstaja 62, recimo temu, nedvoumnih simbolov plus dva, ki se razlikujeta v različnih izvedbah. Čeprav se včasih omenja z izrazom "liki ASCII natisljivi", so v resnici tisti, ki segajo od tistega, ki ga predstavlja koda 32 (presledek) do 126 (~), kar je 95, ki ga je resnično mogoče natisniti.
Izvedba kodiranja Baza64 najbolj uporabljeno, tisto od PEM, ki ga uporablja tudi Mime, delajte z dodatnima znakoma »+« in »/« ter znakom »=«, tako da imajo paketi večkratnik dolžine štiri. Črke A-Z zasedajo položaje 0-25, črke a-z zasedajo položaje 26-51, številke 0-9 zasedajo položaje 52-61, znak plus (+) položaje 62, položaj 63 pa zaseda poševnica (/).
Način predstavitve podatkov v formatu Baza64 sestoji iz vzetja iz izvirnih podatkov skupin 6 bitov ki so predstavljeni z ustrezno kodo. Če ostanejo biti, se zapolnijo z ničlami na desni strani. Če dobljeno število kod ni večkratnik štirih, se izpolni z enakimi znaki na desni strani.
Naslednja slika prikazuje kodiranje ASCII besedila ("ohm") in način, v katerega se pretvori Baza64. Ker je simbolov 7, bi moralo biti končno sporočilo na koncu zapolnjeno z enačajem. Lahko bi rekli, da je besedilo "ohm" v ASCII enakovredno «b2htaW8=" in Baza64.
Posebne uporabe kodiranja Baza64 Običajno določijo tudi največjo dolžino vrstice. Izvedba Mime Vsako vrstico omeji na 76 znakov. Običajno bodo vrstice ločene s kodo konca vrstice (CR, predstavljena z vrednostjo 0x0D v ASCII) in drugo novo vrstico (NL, ki ustreza kodi ASCII 0x0A).
Neprijetnost, ki je dodana pri izvajanju kodiranja Baza64 na napravi z malo viri, kot je pogosto pri a mikrokrmilnik je, da morate kodirati, ko prispejo informacije ali z a varovalni minimum, kar zahteva tudi zagotavljanje sistema, ki označuje, da je bil dosežen konec izvirnega sporočila, na primer z dodajanjem posebne kode ali z uporabo pina, katerega nivo (sinhroniziran s sprejemom) označuje status sporočila.
Spodnji primer kode je a knjižnica za Arduino za kodiranje v Base64 ki se izvaja z obema meriloma: kodiranjem prispele informacije (brez a varovalni) in počakajte, da se konča opozorilni signal.
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”
}
}
|
Temeljni del izračuna kode Baza64 To se naredi z izrazom:
(valor_original>>(2+(numero_valor%3)*2))|resto_base64
in izračun ostanka z izrazom:
(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento
,
biti desplazamiento
vrednost, ki se izračuna z izrazom:
4-(numero_valor%3)*2
Postopek za pridobitev teh izrazov je sestavljen iz posplošitve izračuna vsake od štirih kod Baza64 ki izhajajo iz predstavljanja treh bajtov izvirne vrednosti.
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 |
Z besedilom Base64
Zgornja psevdokoda se nanaša na kodo v Baza64 ki se izračunava. Izraz je bil uporabljen byte_n
za sklicevanje na n-ti bajt, ki je kodiran. Besedilo resto
predstavlja preostale bite bajta, ki se kodira. Na začetku izračuna se predpostavi, da je ostanek enak nič
Zaradi jasnosti je bila v prejšnji psevdokodi 6-bitna maska vključena v izračun vseh kod, čeprav je treba določiti samo zadnjo od njih, saj so druge zasukane, tako da se vedno izgubita dva največja bita. pomemben.
Kot je razvidno, je četrta koda ves ostanek in ostanka ni treba izračunati pozneje; Zato je potrebno izvesti le tri korake, enega na kodiran bajt. Pomembno si je zapomniti, da če tretji bajt v paketu ne bi bil kodiran, bi morala biti zadnja koda izpolnjena z ničlami na desni. Baza64 pridobljeno.
Če posplošimo, desno vrtenje izraza, ki izračuna kodo v Baza64 lahko predstavljamo kot 2+(numero_byte%3)*2
tako da bi se del znotraj oklepaja vrtel od nič do dva, kar bi imelo za posledico 2, 4 in 6 na vsakem koraku. Seveda to ni edini način posploševanja, ampak tega sem izbral zaradi funkcionalnosti in predvsem zaradi jasnosti. Ker je bila maska (AND) potrebna samo v četrti kodi in je bilo že ugotovljeno, da je ni treba izračunati (vse je ostanek), ni vključena v končni izraz, da bi ga poenostavili, čeprav se moramo spomniti da se pri tipu uporabljenih podatkov (bajt) vzame samo 6 najmanj pomembnih bitov.
Levo rotacijo počitka lahko posplošimo na način, ki je analogen prejšnjemu. Vidimo lahko tudi, da je uporabljena maska (AND) podvržena enaki bitni rotaciji, vendar v nasprotni smeri. To je razlog za izračun premika z 4-(numero_valor%3)*2
preden ga uporabite v pomenu, ki ustreza vsakemu delu izraza.
Naslednji primer prikazuje, kako uporabiti knjižnico za kodiranje besedilnega niza (ne pozabite, da Baza64 lahko uporabite za kateri koli niz podatkov, kot je na primer slika). V naslednji kodi je nekaj podrobnosti, ki jih je zanimivo pojasniti. Prvič, za označevanje konca besedila je bil uporabljen poseben simbol (simbol ~) namesto signala strojne opreme ali označevanja dolžine besedila. Logično je, da ta simbol ne more biti del podatkov, ki so kodirani.
Drugo vprašanje, ki ga je treba upoštevati, tako pomembno kot očitno, je, da mora dekoder na cilju vedeti, kako so predstavljene informacije, ki ga dosežejo. V besedilu so znaki, ki ne sodijo v nabor ASCII natisljive (od 32 do 126), črke z naglasom, npr. Arduino bo uporabil dva bajta (UTF-8), ki predstavlja te znake. Običajnega ni mogoče preprosto uporabiti \0
kot zaključek besedila, saj bo v mnogih primerih prvi bajt, s katerim je predstavljen znak, natanko nič.
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()
{
}
|
Vrstica 26 prejšnjega primera prikazuje uporabo knjižnica za Arduino za kodiranje v Base64. Potrebno je samo navesti način convertir
vsak bajt, ki ga želite kodirati, in po želji, ali je zadnji ali, če ni, ustavite pretvorbo z metodo terminar
ko prideš do konca.
Kot je razvidno iz spodnjega posnetka zaslona, je primer programa za knjižnica za Arduino za kodiranje v Base64 najprej prikaže besedilo, ki ga želite kodirati Baza64, v tem primeru začetek slavne pesmi velikanov Les Luthiers, nato pa rezultat kodiranja v Baza64 z uporabo formatne dolžine vrstice Mime.
po Komentar