Arduino を使用した Base64 エンコード ライブラリ
Base64 は、64 の倍数の長さを持つメッセージにグループ化された 65 個のシンボルを使用するコーディング システムです。これらのメッセージ (データ パケット) は、必要に応じてプラス記号 (つまり XNUMX が使用されます)、エンコードされた有用な情報の長さが短くなる場合には等号 (=) で完成します。
64 個の記号を使用して、コードの 10 個の数字と大文字と小文字 (26+26) を操作できます。 ASCII問題は、たとえば 62 個の明確なシンボルと、実装ごとに異なる XNUMX 個のシンボルがあることです。 「キャラクター」という表現で呼ばれることもありますが、 ASCII printable」という名前ですが、実際には、コード 32 (スペース) から 126 (~) で表される実際に印刷可能な 95 までの範囲のものです。
コーディングの実装 Base64 最もよく使われるのは、 PEM、によっても使用されます MIME、パケットの長さが 0 の倍数になるように、追加の「+」および「/」記号と「=」記号を使用して埋め込みます。文字 A ~ Z は位置 25 ~ 26 を占め、文字 a ~ z は位置 51 ~ 0 を占め、数字 9 ~ 52 は位置 61 ~ 62 を占め、プラス記号 (+) は位置 63 を占め、位置 XNUMX はスラッシュ (/) によって占められます。
データをフォーマットで表現する方法 Base64 元のデータから次のグループを取得することで構成されます。 6ビット これらは対応するコードで表されます。ビットが残っている場合は、その右側にゼロが埋められます。結果のコードの数が XNUMX の倍数でない場合は、右側に等号が埋められます。
次の画像はコーディングを示しています ASCII テキスト (「オーム」) の内容と、それがテキストに変換される方法 Base64。記号が 7 つあるため、最終メッセージの最後に等号を入力する必要があります。のテキスト「オーム」は、 ASCII の «b2htaW8=" に相当 Base64.
コーディングの具体的な用途 Base64 また、通常は最大行長も課されます。実装 MIME 各行を 76 文字に制限します。通常、各行は行末コード (CR、値 0x0D で表されます) で区切られます。 ASCII) と別の改行 (NL、コードに対応) ASCII 0x0A)。
コーディングを実装する際に追加される不便さ Base64 リソースがほとんどないデバイスでは、よくあることですが、 マイクロコントローラー つまり、情報が到着したときに、または バッファ これには、たとえば特別なコードを追加するか、メッセージのステータスをレベル (受信と同期) で示すピンを使用することによって、元のメッセージの終わりに達したことを示すシステムを提供することも必要です。
以下のコード例は、 ArduinoがBase64でエンコードするためのライブラリ これは、両方の基準で実装されます: 到着する情報をエンコードする ( バッファ) 警告信号が終了するまで待ちます。
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”
}
}
|
コード計算の基本的な部分 Base64 これは次の式で行われます。
(valor_original>>(2+(numero_valor%3)*2))|resto_base64
次の式で剰余を計算します。
(valor_original&(MASCARA_B64>>desplazamiento))<<desplazamiento
,
さ desplazamiento
次の式で計算される値。
4-(numero_valor%3)*2
これらの式を取得するために実行されるプロセスは、XNUMX つのコードのそれぞれの計算を一般化することで構成されます。 Base64 これは、元の値の XNUMX バイトを表す結果として得られます。
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 |
テキスト付き Base64
上記の疑似コードは、次のコードを参照しています。 Base64 それは計算されているということです。という表現が使われてきました byte_n
エンコードされている n 番目のバイトを参照します。本文 resto
エンコードされるバイトの残りのビットを表します。計算の開始時は、剰余がゼロであると想定されます。
明確にするために、前の疑似コードでは、すべてのコードの計算に 6 ビット マスクが含まれていますが、残りのコードは常に最も多い XNUMX ビットが失われるように回転されるため、決定する必要があるのは最後のコードだけです。重要な。
見てわかるように、XNUMX 番目のコードはすべて剰余であり、その後剰余を計算する必要はありません。したがって、エンコードされたバイトごとに XNUMX つずつ、計 XNUMX つのステップを実行するだけで済みます。パケットの XNUMX 番目のバイトがエンコードされていない場合、最後のコードの右側をゼロで埋める必要があることを覚えておくことが重要です。 Base64 取得しました。
一般化すると、コードを計算する式の右ローテーションは、 Base64 次のように表すことができます 2+(numero_byte%3)*2
括弧内の部分が 2 から 4 に回転し、各ステップで 6、6、XNUMX になります。もちろん、これが一般化する唯一の方法ではありませんが、機能性、そして何よりも明確さのためにこれを選択しました。マスク (AND) は XNUMX 番目のコードでのみ必要であり、それを計算する必要がない (すべて剰余である) ことがすでにわかっているため、簡略化するために最終式には含まれていませんが、覚えておく必要があります。使用されるデータのタイプ (バイト) では、最下位 XNUMX ビットのみが取得されます。
残りの左回転は、前述の方法と同様の方法で一般化できます。また、適用されたマスク (AND) が同じビット回転を逆方向に受けていることもわかります。それが、変位を計算する理由です。 4-(numero_valor%3)*2
式の各部分に対応する意味で適用する前に。
次の例は、ライブラリを使用してテキスト文字列をエンコードする方法を示しています (次の点に注意してください)。 Base64 画像などの任意のデータ セットに使用できます)。次のコードには、明確にしておきたい詳細がいくつかあります。まず、ハードウェア信号やテキストの長さを示す代わりに、テキストの終わりを示すために特別な記号 (~ 記号) が使用されています。論理的には、そのシンボルをエンコードされるデータの一部にすることはできません。
考慮しなければならない XNUMX 番目の問題は、明らかであると同時に重要ですが、宛先のデコーダは、そこに到達する情報がどのように表現されるかを知っていなければならないということです。テキストにセットに属さない文字が含まれています ASCII 印刷可能 (32 ~ 126)、アクセント付きの文字など。 Arduinoの XNUMXバイトを使用します(UTF-8) これらの文字を表します。通常のものは単純に使用できません \0
多くの場合、文字を表す最初のバイトは正確に XNUMX になるため、テキスト ターミネータとして使用されます。
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()
{
}
|
前の例の 26 行目は、 ArduinoがBase64でエンコードするためのライブラリ。方法を示すだけで十分です convertir
エンコードする各バイト、およびオプションでそれが最後のバイトであるか、そうでない場合はメソッドで変換を停止します。 terminar
最後まで到達したとき。
以下のスクリーンショットでわかるように、サンプル プログラムは ArduinoがBase64でエンコードするためのライブラリ 最初にエンコードされるテキストを表示します Base64、この場合、巨人の有名な歌の始まりです。 レ・ルティエ、その後にエンコードされた結果 Base64 フォーマット行の長さを使用する MIME.
コメントを投稿