Arduino ile Base64 kodlama kütüphanesi
Base64 uzunluğu dördün katları olan mesajlar halinde gruplandırılmış 64 sembolü kullanan bir kodlama sistemidir. Bu mesajlar (veri paketleri) gerekirse bir artı simgesiyle (dolayısıyla 65 kullanılır) tamamlanır; kodlanan yararlı bilgiler daha kısa uzunluktaysa genellikle eşittir işareti (=) kullanılır.
64 işaret kullanarak kodun 10 rakamı ve büyük ve küçük harfleri (26+26) ile çalışabilirsiniz. ASCII, sorun şu ki, diyelim ki 62 tane net sembol artı farklı uygulamalarda değişen iki sembol var. Her ne kadar bazen "karakterler" ifadesiyle anılsa da ASCII basılabilir", gerçekte bunlar 32 (boşluk) koduyla temsil edilenden, gerçekten yazdırılabilir 126 olan 95'ya (~) kadar değişen değerlerdir.
Kodlamanın uygulanması Base64 en çok kullanılanı PEMtarafından da kullanılan MIMEPaketlerin uzunluğunun dördün katları olması için ekstra "+" ve "/" işaretleriyle ve "=" işaretiyle çalışın. A-Z harfleri 0-25. konumları, a-z harfleri 26-51. konumları, 0-9 rakamları 52-61. konumları, artı işareti (+) 62. konumları ve 63. konum da eğik çizgi (/) ile doldurulur.
Verileri formatta temsil etmenin yolu Base64 orijinal verilerden grupların alınmasından oluşur 6 bit karşılık gelen kodla temsil edilir. Eğer bitler kalırsa sağdaki sıfırlarla doldurulur. Ortaya çıkan kod sayısı dördün katı değilse sağa doğru eşit işaretlerle doldurulur.
Aşağıdaki resimde kodlama gösterilmektedir ASCII bir metnin ("ohm") ve dönüştürülme şeklinin Base64. 7 sembol olduğundan son mesajın sonuna eşittir işareti konulması gerekir. "Ohm" metninin olduğu söylenebilir. ASCII «b2htaW8=''e eşdeğerdir Base64.
Kodlamanın özel kullanımları Base64 Ayrıca genellikle maksimum hat uzunluğu da uygularlar. Hayata geçirme MIME Her satırı 76 karakterle sınırlar. Normalde satırlar bir satır sonu koduyla (CR, 0x0D değeriyle temsil edilir) ayrılacaktır. ASCII) ve başka bir yeni satır (koda karşılık gelen NL) ASCII 0x0A).
Kodlamayı uygularken eklenen rahatsızlık Base64 az sayıda kaynağa sahip bir cihazda, çoğu zaman olduğu gibi mikrodenetleyici bilgi geldikçe veya bir kodla kodlamanız gerektiğidir. tampon Bu aynı zamanda, örneğin özel bir kod ekleyerek veya seviyesi (alımla senkronize edilmiş) mesajın durumunu gösteren bir pin kullanarak orijinal mesajın sonuna ulaşıldığını belirten bir sistemin sağlanmasını gerektirir.
Aşağıdaki örnek kod bir Arduino'nun Base64'te kodlayacağı kütüphane her iki kriterle de uygulanır: gelen bilginin kodlanması ( tampon) ve bir uyarı sinyalinin bitmesini bekleyin.
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”
}
}
|
Kod hesaplamasının temel kısmı Base64 Şu ifadeyle yapılır:
(valor_original>>(2+(numero_valor%3)*2))|resto_base64
ve kalanın şu ifadeyle hesaplanması:
(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento
,
olma desplazamiento
şu ifadeyle hesaplanan bir değer:
4-(numero_valor%3)*2
Bu ifadeleri elde etmek için izlenen süreç, dört kodun her birinin hesaplanmasının genelleştirilmesinden oluşur. Base64 bu, orijinal değerin üç baytını temsil etmenin sonucudur.
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 |
metin ile Base64
Yukarıdaki sözde kod, içindeki kodu ifade eder. Base64 bu hesaplanıyor. İfade kullanıldı byte_n
kodlanan n'inci bayta atıfta bulunmak için. Metin resto
kodlanan baytın kalan bitlerini temsil eder. Hesaplamanın başında kalanın sıfır olduğu varsayılır.
Açıklık sağlamak için, önceki sözde kodda 6 bitlik maske tüm kodların hesaplanmasına dahil edilmiştir, ancak yalnızca sonuncusunu belirlemek gerekir, çünkü diğerleri döndürülür ve böylece en fazla iki bit her zaman kaybolur. önemli.
Görüldüğü gibi dördüncü kod tamamen kalandır ve sonradan bir kalan hesaplamaya gerek yoktur; Bu nedenle, kodlanmış bayt başına bir tane olmak üzere yalnızca üç adımı gerçekleştirmek gerekir. Bir paketteki üçüncü bayt kodlanmamışsa, son kodun sağdaki sıfırlarla doldurulması gerekeceğini unutmamak önemlidir. Base64 elde edilmiştir.
Genelleştirmek gerekirse, kodu hesaplayan ifadenin sağa döndürülmesi Base64 olarak temsil edilebilir 2+(numero_byte%3)*2
böylece parantez içindeki kısım sıfırdan ikiye dönecek ve her adımda 2, 4 ve 6 elde edilecektir. Tabii ki genelleme yapmanın tek yolu bu değil ama bunu işlevsellik ve her şeyden önce netlik açısından seçtim. Maske (AND) yalnızca dördüncü kodda gerekli olduğundan ve hesaplanmasına gerek olmadığı zaten görüldüğünden (hepsi geri kalandır), basitleştirmek için son ifadeye dahil edilmemiştir, ancak hatırlamamız gerekir. kullanılan veri türünde (bayt) yalnızca en az anlamlı 6 bit alınır.
Geri kalanın sola dönüşü öncekine benzer bir şekilde genelleştirilebilir. Ayrıca uygulanan maskenin (AND) aynı bit dönüşüne ancak ters yönde maruz kaldığı da görülebilir. Yer değiştirmenin hesaplanmasının nedeni budur. 4-(numero_valor%3)*2
ifadenin her bir kısmına karşılık gelen anlamda uygulamadan önce.
Aşağıdaki örnek, bir metin dizesini kodlamak için kitaplığın nasıl kullanılacağını gösterir (unutmayın: Base64 örneğin bir görüntü gibi herhangi bir veri kümesi için kullanılabilir). Aşağıdaki kodda açıklığa kavuşturulması ilginç olan birkaç ayrıntı vardır. İlk olarak, bir donanım sinyali veya metnin uzunluğunu belirtmek yerine, metnin sonunu belirtmek için özel bir simge (~ simgesi) kullanıldı. Mantıksal olarak bu sembol, kodlanan verinin bir parçası olamaz.
Dikkate alınması gereken ikinci konu, her ne kadar açık olsa da, hedefteki kod çözücünün kendisine ulaşan bilginin nasıl temsil edildiğini bilmesi gerektiğidir. Metin sete ait olmayan karakterler içeriyor ASCII yazdırılabilir (32'den 126'ya kadar), örneğin aksanlı harfler. Arduino iki bayt kullanacak (UTF-8) bu karakterleri temsil etmek için. Her zamanki gibi basitçe kullanılamaz \0
Çoğu durumda bir karakterin temsil edildiği ilk bayt tam olarak sıfır olacağından metin sonlandırıcı olarak kullanılır.
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()
{
}
|
Önceki örneğin 26. satırında kullanımı gösterilmektedir. Arduino'nun Base64'te kodlayacağı kütüphane. Sadece yöntemi belirtmek gerekir convertir
kodlamak istediğiniz her bayt ve isteğe bağlı olarak sonuncusu olup olmadığı veya değilse, yöntemle dönüşümü durdurun terminar
sona ulaştığınızda.
Aşağıdaki ekran görüntüsünde görüldüğü gibi örnek program Arduino'nun Base64'te kodlayacağı kütüphane ilk önce kodlanacak metni görüntüler Base64bu durumda devlerin meşhur şarkısının başlangıcı Les Luthiersve ardından kodlamanın sonucu Base64 format satırı uzunluğunu kullanma MIME.
Yorum Ekle