Base64 encoding library gamit ang Arduino
Basexnumx ay isang coding system na gumagamit ng 64 na simbolo na pinagsama-sama sa mga mensahe na may haba na multiple ng apat. Ang mga mensaheng ito (mga data packet) ay nakumpleto, kung kinakailangan, na may plus na simbolo (kaya 65 ang ginagamit), kadalasan ang katumbas na tanda (=), kung ang kapaki-pakinabang na impormasyong naka-encode ay nagreresulta sa mas maikling haba.
Gamit ang 64 na mga senyales, maaari kang gumamit ng 10 numero at malaki at maliit na titik (26+26) ng code ASCII, ang problema ay mayroong 62, sabihin nating, hindi malabo na mga simbolo kasama ang dalawa na nag-iiba sa iba't ibang pagpapatupad. Bagama't minsan ay tinutukoy ng ekspresyong "mga character ASCII printable", sa katotohanan ang mga ito ay mula sa isang kinakatawan ng code 32 (space) hanggang 126 (~) ang 95 na tunay na napi-print.
Ang pagpapatupad ng coding Basexnumx pinaka ginagamit, na ng PEM, na ginagamit din ng Mime, gumana sa mga dagdag na "+" at "/" na mga palatandaan at ang "=" sign sa pad upang ang mga packet ay may haba na maramihang apat. Ang mga titik A-Z ay sumasakop sa mga posisyon 0-25, ang mga titik a-z ay sumasakop sa mga posisyon 26-51, ang mga numero 0-9 ay sumasakop sa mga posisyon na 52-61, ang plus sign (+) na mga posisyon 62, at ang posisyon 63 ay sinasakop ng slash (/ ).
Ang paraan upang kumatawan sa data sa format Basexnumx binubuo ng pagkuha, mula sa orihinal na data, mga pangkat ng 6 bits na kinakatawan ng kaukulang code. Kung may mga piraso na natitira, sila ay puno ng mga zero sa kanan. Kung ang resultang bilang ng mga code ay hindi isang multiple ng apat, ito ay pupunan ng pantay na mga palatandaan sa kanan.
Ang sumusunod na larawan ay nagpapakita ng coding ASCII ng isang text ("ohm") at ang paraan kung saan ito na-convert sa Basexnumx. Dahil mayroong 7 simbolo, ang huling mensahe ay kailangang punan ng katumbas na tanda sa dulo. Maaaring sabihin na ang tekstong "ohm" ay nasa ASCII katumbas ng «b2htaW8=" sa Basexnumx.
Mga partikular na gamit ng coding Basexnumx Karaniwan din silang nagpapataw ng maximum na haba ng linya. Ang pagpapatupad Mime Nililimitahan ang bawat linya sa 76 na character. Karaniwan ang mga linya ay paghihiwalayin ng isang end-of-line code (CR, na kinakatawan ng value na 0x0D sa ASCII) at isa pang bagong linya (NL, na tumutugma sa code ASCII 0x0A).
Ang abala na idinagdag kapag nagpapatupad ng coding Basexnumx sa isang device na may kaunting mapagkukunan, gaya ng kadalasang nangyayari sa a microcontroller ay kailangan mong mag-code habang dumating ang impormasyon o may a nagpapahina ng lakas minimum, na nangangailangan din ng pagbibigay ng isang sistema na nagsasaad na ang dulo ng orihinal na mensahe ay naabot na, halimbawa, sa pamamagitan ng pagdaragdag ng isang espesyal na code, o sa pamamagitan ng paggamit ng isang pin na ang antas (naka-synchronize sa pagtanggap) ay nagpapahiwatig ng katayuan ng mensahe.
Ang halimbawang code sa ibaba ay a library para sa Arduino na mag-encode sa Base64 na ipinapatupad sa parehong pamantayan: pag-encode ng impormasyon na dumating (nang walang a nagpapahina ng lakas) at maghintay para matapos ang isang senyas ng babala.
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”
}
}
|
Ang pangunahing bahagi ng pagkalkula ng code Basexnumx Ginagawa ito gamit ang expression:
(valor_original>>(2+(numero_valor%3)*2))|resto_base64
at ang pagkalkula ng natitira gamit ang expression:
(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento
,
pagkatao desplazamiento
isang halaga na kinakalkula gamit ang expression:
4-(numero_valor%3)*2
Ang prosesong sinundan para makuha ang mga expression na ito ay binubuo ng pag-generalize ng kalkulasyon ng bawat isa sa apat na code Basexnumx na resulta mula sa kumakatawan sa tatlong byte ng orihinal na halaga.
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 |
Gamit ang text Base64
Ang pseudocode sa itaas ay tumutukoy sa code sa Basexnumx iyon ay kinakalkula. Ang ekspresyon ay ginamit byte_n
upang sumangguni sa nth byte na naka-encode. Ang teksto resto
kumakatawan sa mga natitirang bit ng byte na naka-encode. Sa simula ng pagkalkula ay ipinapalagay na ang natitira ay zero
Para sa kalinawan, sa nakaraang pseudocode ang 6-bit na mask ay kasama sa pagkalkula ng lahat ng mga code, bagaman kinakailangan lamang upang matukoy ang huli sa mga ito, dahil ang iba ay pinaikot upang ang dalawang pinaka-bit ay palaging nawala. makabuluhan.
Tulad ng makikita, ang ikaapat na code ay ang lahat ng natitira at hindi na kailangang kalkulahin ang isang natitira pagkatapos; Samakatuwid, kinakailangan lamang na magsagawa ng tatlong hakbang, isa sa bawat naka-encode na byte. Mahalagang tandaan na, kung ang ikatlong byte sa isang packet ay hindi na-encode, ang huling code ay kailangang punan ng mga zero sa kanan. Basexnumx nakuha.
Upang gawing pangkalahatan, ang tamang pag-ikot ng expression na kinakalkula ang code sa Basexnumx maaaring katawanin bilang 2+(numero_byte%3)*2
upang ang bahagi sa loob ng mga panaklong ay umiikot mula sa zero hanggang dalawa, na nagreresulta sa 2, 4 at 6 sa bawat hakbang. Siyempre hindi lang ito ang paraan para gawing pangkalahatan, ngunit pinili ko ang isang ito para sa pag-andar at higit sa lahat para sa kalinawan. Dahil ang mask (AT) ay kailangan lamang sa ika-apat na code at nakita na na hindi na kailangang kalkulahin ito (lahat ng natitira), hindi ito kasama sa panghuling pagpapahayag upang pasimplehin ito, bagama't dapat nating tandaan na ang uri ng data na ginamit (byte ) lamang ang 6 na pinakamaliit na makabuluhang bits ang kinukuha.
Ang kaliwang pag-ikot ng natitira ay maaaring pangkalahatan sa isang paraan na kahalintulad sa nauna. Makikita rin na ang mask na inilapat (AT) ay sumasailalim sa parehong bit rotation ngunit sa kabaligtaran ng direksyon. Iyon ang dahilan ng pagkalkula ng displacement sa 4-(numero_valor%3)*2
bago ilapat ito sa kahulugang naaayon sa bawat bahagi ng pagpapahayag.
Ang sumusunod na halimbawa ay nagpapakita kung paano gamitin ang library para mag-encode ng text string (tandaan na Basexnumx maaaring gamitin para sa anumang set ng data, tulad ng isang larawan, halimbawa). Sa sumusunod na code mayroong ilang mga detalye na kawili-wiling linawin. Una, ang isang espesyal na simbolo (ang ~ simbolo) ay ginamit upang ipahiwatig ang dulo ng teksto, sa halip na isang signal ng hardware o nagpapahiwatig ng haba ng teksto. Logically, ang simbolo na iyon ay hindi maaaring maging bahagi ng data na naka-encode.
Ang ikalawang isyu na dapat isaalang-alang, bilang mahalaga bilang ito ay halata, ay na ang decoder sa destinasyon ay dapat malaman kung paano ang impormasyon na umaabot dito ay kinakatawan. Kasama sa text ang mga character na hindi kabilang sa set ASCII napi-print (mula 32 hanggang 126), mga titik na may accent, halimbawa. Arduino gagamit ng dalawang byte (UTF-8) upang kumatawan sa mga karakter na ito. Ang karaniwan ay hindi basta-basta magagamit \0
bilang isang text terminator dahil, sa maraming kaso, ang unang byte kung saan kinakatawan ang isang character ay magiging tiyak na zero.
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()
{
}
|
Ang linya 26 ng nakaraang halimbawa ay nagpapakita ng paggamit ng library para sa Arduino na mag-encode sa Base64. Kinakailangan lamang na ipahiwatig ang pamamaraan convertir
bawat byte na gusto mong i-encode at opsyonal kung ito ang huli o, kung hindi, itigil ang conversion gamit ang pamamaraan terminar
kapag umabot ka sa dulo.
Tulad ng makikita sa screenshot sa ibaba, ang halimbawang programa ng library para sa Arduino na mag-encode sa Base64 unang ipinapakita ang tekstong ie-encode Basexnumx, sa kasong ito, ang simula ng sikat na kanta ng mga higante Les Luthiers, at pagkatapos ay ang resulta ng pag-encode sa Basexnumx gamit ang haba ng linya ng format Mime.
Post Komento