Compare commits

..

67 Commits

Author SHA1 Message Date
philippe44
d27825d62c Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2025-12-26 21:53:56 +01:00
philippe44
a33f699dc7 fix messages 2025-12-26 21:53:43 +01:00
philippe44
70a79b8731 Update Platform_build.yml 2025-12-26 21:45:05 +01:00
philippe44
b585f24f37 Create client_info.h 2025-12-26 21:43:51 +01:00
philippe44
9d8be934ac Update CMakeLists.txt 2025-12-26 21:37:35 +01:00
philippe44
d55768ffe1 Update CMakeLists.txt 2025-12-26 21:35:33 +01:00
philippe44
dd62f1aae6 Update Platform_build.yml 2025-12-26 21:23:41 +01:00
philippe44
adfb8b0767 Delete components/spotify/client_info.h 2025-12-26 21:21:55 +01:00
philippe44
83d6322bcf Update client_info.h 2025-12-26 21:14:07 +01:00
philippe44
cd56b20a06 Update Platform_build.yml 2025-12-26 20:43:33 +01:00
github-actions
ec60400673 Update prebuilt objects [skip actions] 2025-12-26 17:16:37 +00:00
philippe44
25f4855375 Update Platform_build.yml 2025-12-26 18:07:49 +01:00
philippe44
1d21662f89 Update Platform_build.yml 2025-12-26 18:05:22 +01:00
philippe44
1835423924 Update Platform_build.yml 2025-12-26 18:04:16 +01:00
philippe44
2abdd91aa6 Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2025-12-26 18:02:33 +01:00
philippe44
d7093b0bab Spotify secrets 2025-12-26 18:02:29 +01:00
philippe44
4d36958008 Update Platform_build.yml 2025-12-26 17:24:47 +01:00
philippe44
2d90c823af Update Platform_build.yml 2025-12-26 17:20:20 +01:00
philippe44
289026527b Spotify 2025-12-25 12:22:18 +01:00
philippe44
bca8c21322 Merge pull request #511 from Jeeere/master-v4.3
Fix PCM5102 pin configuration example in README.md
2025-12-25 12:14:54 +01:00
philippe44
f6763ebead Merge pull request #521 from RASPIAUDIO/master-v4.3
Raspiaudio Muse Luxe 2025/11/26
2025-12-25 12:13:29 +01:00
philippe44
f64c09cf30 Update README.md 2025-12-25 12:05:40 +01:00
philippe44
c0d2add55b Use client id & secret for Spotify 2025-12-25 00:02:02 +01:00
philippe44
1e3de24bdf ignore 2025-12-24 19:24:31 +01:00
philippe44
f87d38b5e9 add client_info 2025-12-24 19:24:10 +01:00
RASPIAUDIOadmin
23234f7189 Raspiaudio 2025/11/26 2025-11-26 12:03:56 +01:00
Jere
9f783b6b5d Fix PCM5102 pin configuration example in README.md
Add missing newline
Change SCL to SCK
2025-10-09 13:50:40 +03:00
philippe44
752cfbf3b2 Update .gitattributes 2025-03-30 14:19:09 +02:00
philippe44
cecb7fd876 Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2025-02-17 23:26:07 +01:00
philippe44
e92e431b45 add MCK in get_dac_config 2025-02-17 23:26:01 +01:00
philippe44
db792e47bd Update Platform_build.yml 2025-02-17 22:47:05 +01:00
philippe44
a22f75a13a limit display checks 2025-02-17 22:39:48 +01:00
philippe44
1f220895e6 Update README.md 2025-02-17 12:55:44 +01:00
philippe44
769ff99f7d Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2024-09-28 23:17:23 +02:00
philippe44
424fb93ec4 add 2nd encoder for volume only 2024-09-28 23:17:09 +02:00
philippe44
e270963dbd Update README.md 2024-09-28 23:11:52 +02:00
philippe44
2cae41d29c Update README.md 2024-09-28 23:11:10 +02:00
philippe44
84b95cd79c Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2024-09-28 18:55:48 +02:00
philippe44
6369f4bd69 another misplaced NVS #ifdef 2024-09-28 18:55:43 +02:00
philippe44
4c1bca3166 Update CHANGELOG 2024-09-28 14:43:23 +02:00
philippe44
3a5163e6f6 Update esp_app_main.c
autoexec default was created at the wrong place!
2024-09-28 14:42:08 +02:00
philippe44
cbe42b56bc Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2024-09-27 18:53:46 +02:00
philippe44
ab9812cb75 make i2s emergency stop platform independant 2024-09-27 18:52:26 +02:00
philippe44
084caedd7e Update README.md 2024-09-27 16:35:15 +02:00
philippe44
f254bf49af Update README.md 2024-09-27 15:35:59 +02:00
philippe44
66bd26f007 Update README.md 2024-09-27 15:35:03 +02:00
philippe44
dd6c932c39 Update README.md 2024-09-27 15:06:38 +02:00
philippe44
50070378ad Merge pull request #440 from digidocs/loudness_plugin_fix1
SqueezeESP32 plugin loudness control fix
2024-09-12 12:33:31 +02:00
github-actions
b50bc8f376 Update prebuilt objects [skip actions] 2024-09-12 09:32:21 +00:00
philippe44
e6723dfa2f Update CHANGELOG 2024-09-12 11:27:55 +02:00
philippe44
ffaff5ac27 Merge pull request #430 from StefanKrupop/aw9523_expander
Add support for AW9523 GPIO expander
2024-09-12 11:25:31 +02:00
philippe44
33ef4b01e7 Update CHANGELOG 2024-09-12 11:24:23 +02:00
github-actions
302865b167 Update prebuilt objects [skip actions] 2024-09-11 18:05:43 +00:00
philippe44
7f0ae69e81 Merge pull request #439 from digidocs/eq_update_fix2
Fix for ESP32 equalizer settings don't update when expected
2024-09-11 20:02:25 +02:00
David Carr
e21e2cf7f9 Equalizer: change gain to int8 and memcmp-based update check 2024-09-04 15:07:42 -05:00
David Carr
57cd009e4c Revert "Equalizer: check if requested gain has changed before updating"
This reverts commit 78e8d60021.
2024-09-04 14:52:27 -05:00
David Carr
fdd8b0a4c9 Change to //= operator 2024-09-04 14:48:07 -05:00
David Carr
78e8d60021 Equalizer: check if requested gain has changed before updating 2024-09-04 13:49:51 -05:00
digidocs
4068e07a45 Fix for I2S noise burst when ESP32 panic occurs (#437) 2024-09-02 08:51:40 -04:00
David Carr
f8d7ac23e1 Updated SqueezeESP32 plugin and zip file 2024-08-21 12:07:57 -05:00
David Carr
befc81f573 Fix for wrong loudness value being sent when user requests loudness 0 2024-08-21 11:01:18 -05:00
David Carr
a633524936 Fix for ESP32 equalizer settings don't update when expected 2024-08-21 00:08:06 -05:00
Stefan Krupop
9d71b8ee26 Added "aw9523" to list of possible expanders 2024-07-26 21:01:10 +02:00
Stefan Krupop
672aca8258 Fixed resetting interrupt 2024-07-26 20:18:55 +02:00
Stefan Krupop
a2351ba0d5 Add support for AW9523 port expander 2024-07-25 01:13:14 +02:00
wizmo2
40a698e2f1 add checks for grfX handlers to prevent divide-by-zero with slimproto (#424)
Thank you!
2024-06-07 18:19:33 -04:00
github-actions
38d28ae8c4 Update prebuilt objects [skip actions] 2024-05-07 21:41:36 +00:00
71 changed files with 706 additions and 470 deletions

2
.gitattributes vendored
View File

@@ -1,5 +1,5 @@
# Auto detect text files and perform LF normalization
* text=auto
# * text=auto
# Custom for Visual Studio
*.cs diff=csharp

View File

@@ -136,6 +136,8 @@ jobs:
name: prebuilt_objects
- name: Build the firmware
if: ${{ needs.bootstrap.outputs.mock == 0 }}
env:
SPOTIFY_SECRET: -DCLIENT_ID="${{ secrets.SPOTIFY_CLIENT_ID }}" -DCLIENT_SECRET="${{ secrets.SPOTIFY_CLIENT_SECRET }}"
run: |
. ${IDF_PYTHON_ENV_PATH}/bin/activate
echo "Copying target sdkconfig"
@@ -171,7 +173,7 @@ jobs:
zip build/${artifact_file_name} partitions*.csv components/ build/*.bin build/bootloader/bootloader.bin build/partition_table/partition-table.bin build/flash_project_args build/size_*.txt
fi
- name: Upload Build Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: ${{ needs.bootstrap.outputs.mock == 0 }}
with:
name: ${{ env.artifact_prefix }}

1
.gitignore vendored
View File

@@ -18,3 +18,4 @@ components/wifi-manager/UML-State-Machine-in-C
envfile.txt
artifacts
web-installer
client_info.h

View File

@@ -1,3 +1,24 @@
2025-12-25
- Use dedicated client_id and client_secret for spotify
2025-02-17
- reverse some checks on display not NULL in gds.c. As it is about being fast, I'd prefer the caller to know that there is no display and don't call. I'm sure I have missed something when there is only led_vu and no display, but people will remind me soon enough :-)
2024-09-28
- add dedicated volume encoder
- fix memory leak in rotary config creation
2024-09-28
- create autoexec NVS entry at the right place (not only whne BT is enabled!
- try to make i2s panic mode work for all esp versions
2024-09-12
- add AW9523 GPIO expander credits @Stefan Krupop (https://github.com/sle118/squeezelite-esp32/pull/430
2024-09-10
- Merge pull request # 439 from digidocs/eq_update_fix2 (# 309)
- Fix for I2S noise burst when ESP32 panic occurs (# 437)
2024-05-05
- Fix crash when led_vu is configured without display
2024-01-27

View File

@@ -73,7 +73,7 @@ set_target_properties(recovery.elf PROPERTIES LINK_LIBRARIES "${BCA};idf::app_re
# build squeezelite, add app_squeezelite to the link
add_executable(squeezelite.elf "CMakeLists.txt")
add_dependencies(squeezelite.elf recovery.elf)
set_target_properties(squeezelite.elf PROPERTIES LINK_LIBRARIES "${BCA};idf::app_squeezelite;-Wl,--Map=${BUILD_DIR}/squeezelite.map")
set_target_properties(squeezelite.elf PROPERTIES LINK_LIBRARIES "${BCA};idf::app_squeezelite;-Wl,--Map=${BUILD_DIR}/squeezelite.map,--wrap=esp_panic_handler")
add_custom_command(
TARGET squeezelite.elf
POST_BUILD
@@ -228,4 +228,4 @@ endif()
# target_compile_definitions(__idf_wear_levelling PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
# target_compile_definitions(__idf_wifi_provisioning PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
# target_compile_definitions(__idf_wpa_supplicant PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
# target_compile_definitions(__idf_xtensa PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)
# target_compile_definitions(__idf_xtensa PRIVATE -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG)

View File

@@ -15,6 +15,7 @@ Depending on the hardware connected to the esp32, you can send audio to a local
But squeezelite-esp32 is highly extensible and you can add
- [Buttons](#buttons) and [Rotary Encoder](#rotary-encoder) and map/combine them to various functions (play, pause, volume, next ...)
- [Volume Encoder](#volume-rotary-encoder) for a dedicated volume rotary encoder
- [GPIO expander](#gpio-expanders) (buttons, led and rotary)
- [IR receiver](#infrared) (no pullup resistor or capacitor needed, just the 38kHz receiver)
- [Monochrome, GrayScale or Color displays](#display) using SPI or I2C (supported drivers are SH1106, SSD1306, SSD1322, SSD1326/7, SSD1351, ST7735, ST7789 and ILI9341).
@@ -147,12 +148,12 @@ VCC - 3.3V
GND - GND
FLT - GND
DMP - GND
SCL - GND
SCK - GND
BCK - (BCK - see below)
DIN - (DO - see below)
LCK - (WS - see below)
LCK - (WS - see below)
FMT - GND
XMT - 3.3V
XMT - 3.3V
Use the `squeezelite-esp32-I2S-4MFlash-sdkconfig.defaults` configuration file.
@@ -237,13 +238,14 @@ Ground -------------------------- coax signal ground
### Display
The NVS parameter "display_config" sets the parameters for an optional display. It can be I2C (see [here](#i2c) for shared bus) or SPI (see [here](#spi) for shared bus) Syntax is
```
I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,reset=<gpio>][,HFlip][,VFlip][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106]
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735|ST7789[:x=<offset>][:y=<offset>]|ILI9341[:16|18][,rotate]]
I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,reset=<gpio>][,HFlip][,VFlip][,invert][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106]
SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][,invert][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735|ST7789[:x=<offset>][:y=<offset>]|ILI9341[:16|18][,rotate]]
```
- back: a LED backlight used by some older devices (ST7735). It is PWM controlled for brightness
- reset: some display have a reset pin that is should normally be pulled up if unused. Most displays require reset and will not initialize well otherwise.
- VFlip and HFlip are optional can be used to change display orientation
- rotate: for non-square *drivers*, move to portrait mode. Note that *width* and *height* must be inverted then
- invert: invert each pixel colorspace
- Default speed is 8000000 (8MHz) but SPI can work up to 26MHz or even 40MHz
- SH1106 is 128x64 monochrome I2C/SPI [here](https://www.waveshare.com/wiki/1.3inch_OLED_HAT)
- SSD1306 is 128x32 monochrome I2C/SPI [here](https://www.buydisplay.com/i2c-blue-0-91-inch-oled-display-module-128x32-arduino-raspberry-pi)
@@ -308,7 +310,7 @@ The parameter "gpio_exp_config" is a semicolon (;) separated list with following
```
model=<model>,addr=<addr>,[,port=system|dac][,base=<n>][,count=<n>][,intr=<gpio>][,cs=<gpio>][,speed=<Hz>]
```
- model: pca9535, pca85xx, mcp23017 and mcp23s17 (SPI version)
- model: pca9535, pca85xx, mcp23017, aw9523 and mcp23s17 (SPI version)
- addr: chip i2c/spi address (decimal)
- port (I2C): use either "system" port (shared with display for example) or "dac" port (system is default)
- cs (SPI): gpio used for Chip Select
@@ -341,9 +343,9 @@ The latest LMS plugin update is required to set the visualizer mode and brightne
| \<playerid\> dmx \<R,G,B,R,G,B, ... R,G,B\> \[\<offset\>\] | Sets the LED color starting at position "offset"<br /> with "R"(red),"G"(green),and "B"(blue) color sequences.<br />Add additional RGB values to the delimited string to set multiple LEDs.<br /> |
### Rotary Encoder
One rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by software.
One general rotary encoder is supported, quadrature shift with press. Such encoders usually have 2 pins for encoders (A and B), and common C that must be set to ground and an optional SW pin for press. A, B and SW must be pulled up, so automatic pull-up is provided by ESP32, but you can add your own resistors. A bit of filtering on A and B (~470nF) helps for debouncing which is not made by software.
Encoder is normally hard-coded to respectively knob left, right and push on LMS and to volume down/up/play toggle on BT and AirPlay. Using the option 'volume' makes it hard-coded to volume down/up/play toggle all the time (even in LMS). The option 'longpress' allows an alternate mode when SW is long-pressed. In that mode, left is previous, right is next and press is toggle. Every long press on SW alternates between modes (the main mode actual behavior depends on 'volume').
Encoder is normally hard-coded to respectively knob left, right and push on LMS and to volume down/up/play toggle on BT, AirPlay and Spotify. Using the option 'volume' makes it hard-coded to volume down/up/play toggle all the time (even in LMS). The option 'longpress' allows an alternate mode when SW is long-pressed. In that mode, left is previous, right is next and press is toggle. Every long press on SW alternates between modes (the main mode actual behavior depends on 'volume').
There is also the possibility to use 'knobonly' option (exclusive with 'volume' and 'longpress'). This mode attempts to offer a single knob full navigation which is a bit contorded due to LMS UI's principles. Left, Right and Press obey to LMS's navigation rules and especially Press always goes to lower submenu item, even when navigating in the Music Library. That causes a challenge as there is no 'Play', 'Back' or 'Pause' button. Workaround are as of below:
- longpress is 'Play'
@@ -364,7 +366,16 @@ The SW gpio is optional, you can re-affect it to a pure button if you prefer but
See also the "IMPORTANT NOTE" on the "Buttons" section and remember that when 'lms_ctrls_raw' (see below) is activated, none of these knobonly,volume,longpress options apply, raw button codes (not actions) are simply sent to LMS
**Note that gpio 36 and 39 are input only and cannot use interrupt, so they cannot be set to A or B. When using them for SW, a 100ms polling is used which is expensive**
**Note that on esp32, gpio 36 and 39 are input only and cannot use interrupt, so they cannot be set to A or B. When using them for SW, a 100ms polling is used which is expensive**
### Volume Rotary Encoder
One dedicated volume rotary encoder is supported, quadrature shift with press. Encoder is hard-coded to volume-up, down and play toggle for LMS, BT, AirPlay and Spotify (see note above for filtering and HW note as well GPIO 36 and 39 on esp32)
Use parameter volume_rotary with the following syntax:
```
A=<gpio>,B=<gpio>[,SW=gpio>]
```
### Buttons
Buttons are described using a JSON string with the following syntax
@@ -632,10 +643,14 @@ docker run -it -v `pwd`:/workspace/squeezelite-esp32 sle118/squeezelite-esp32-id
The above command will mount this repo into the docker container and start a bash terminal. From there, simply run idf.py build to build, etc. Note that at the time of writing these lines, flashing is not possible for docker running under windows https://github.com/docker/for-win/issues/1018.
### Manual Install of ESP-IDF
You can install IDF manually on Linux or Windows (using the Subsystem for Linux) following the instructions at: https://www.instructables.com/id/ESP32-Development-on-Windows-Subsystem-for-Linux/ or see here https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html for a direct install. You also need a few extra Python libraries for cspot by addingsudo `pip3 install protobuf grpcio-tools`
**Use the esp-idf 4.3.5 https://github.com/espressif/esp-idf/tree/release/v4.3.5 ** or the 4.4.5 (and above version) if you want to build for esp32-s3
First you need git and python (e.g 3.10.x), install these and let it add to system path.
**Use the esp-idf 4.3.5 https://github.com/espressif/esp-idf/tree/release/v4.3.5 ** or the 4.4.5 (and above version) if you want to build for esp32-s3. You should clone recursively the whole branch (at the version you need) `git clone -b v4.3.5 https://github.com/espressif/esp-idf --recursive`and run the installer (`install.bat [esp32[,esp32s3]]` from there. Some Windows version (at least) have now a SSL certificate issue. You can workaround this by editing idf-tools.py and adding the following under ìmport ssl`
```
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
```
And because the fun never ends, some Windows installations might fail to build a few files and spit a tons of errors on the output. It seems that the cache of the compile is a problem, so try to disable it by running `idf.py --no-ccache build` (I know...)
## Building SqueezeESP32
When initially cloning the repo, make sure you do it recursively. For example: `git clone --recursive https://github.com/sle118/squeezelite-esp32.git`. You also should install cspot additional components for protobuf use.
```

View File

@@ -54,7 +54,6 @@ struct GDS_Device* GDS_AutoDetect( char *Driver, GDS_DetectFunc* DetectFunc[], s
}
void GDS_ClearExt(struct GDS_Device* Device, bool full, ...) {
GDS_CHECK_FOR_DEVICE(Device,return);
bool commit = true;
if (full) {
@@ -75,7 +74,6 @@ void GDS_ClearExt(struct GDS_Device* Device, bool full, ...) {
}
void GDS_Clear( struct GDS_Device* Device, int Color ) {
GDS_CHECK_FOR_DEVICE(Device,return);
if (Color == GDS_COLOR_BLACK) memset( Device->Framebuffer, 0, Device->FramebufferSize );
else if (Device->Depth == 1) memset( Device->Framebuffer, 0xff, Device->FramebufferSize );
else if (Device->Depth == 4) memset( Device->Framebuffer, Color | (Color << 4), Device->FramebufferSize );
@@ -91,7 +89,6 @@ void GDS_Clear( struct GDS_Device* Device, int Color ) {
}
void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ) {
GDS_CHECK_FOR_DEVICE(Device,return);
// -1 means up to width/height
if (x2 < 0) x2 = Device->Width - 1;
if (y2 < 0) y2 = Device->Height - 1;
@@ -161,13 +158,11 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
}
void GDS_Update( struct GDS_Device* Device ) {
GDS_CHECK_FOR_DEVICE(Device,return);
if (Device->Dirty) Device->Update( Device );
Device->Dirty = false;
}
bool GDS_Reset( struct GDS_Device* Device ) {
GDS_CHECK_FOR_DEVICE(Device,return false);
if ( Device->RSTPin >= 0 ) {
gpio_set_level( Device->RSTPin, 0 );
vTaskDelay( pdMS_TO_TICKS( 100 ) );
@@ -232,7 +227,7 @@ static void IRAM_ATTR DrawPixel24Fast( struct GDS_Device* Device, int X, int Y,
}
bool GDS_Init( struct GDS_Device* Device ) {
GDS_CHECK_FOR_DEVICE(Device,return false);
if (Device->Depth > 8) Device->FramebufferSize = Device->Width * Device->Height * ((8 + Device->Depth - 1) / 8);
else Device->FramebufferSize = (Device->Width * Device->Height) / (8 / Device->Depth);
@@ -279,7 +274,6 @@ bool GDS_Init( struct GDS_Device* Device ) {
}
int GDS_GrayMap( struct GDS_Device* Device, uint8_t Level) {
GDS_CHECK_FOR_DEVICE(Device,return -1);
switch(Device->Mode) {
case GDS_MONO: return Level;
case GDS_GRAYSCALE: return Level >> (8 - Device->Depth);
@@ -306,7 +300,6 @@ int GDS_GrayMap( struct GDS_Device* Device, uint8_t Level) {
}
void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
GDS_CHECK_FOR_DEVICE(Device,return);
if (Device->SetContrast) Device->SetContrast( Device, Contrast );
else if (Device->Backlight.Pin >= 0) {
Device->Backlight.PWM = PWMConfig.Max * powf(Contrast / 255.0, 3);
@@ -315,12 +308,12 @@ void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
}
}
void GDS_SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { if (Device && Device->SetLayout) Device->SetLayout( Device, Layout ); }
void GDS_SetDirty( struct GDS_Device* Device ) { GDS_CHECK_FOR_DEVICE(Device,return); Device->Dirty = true; }
void GDS_SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { if (Device->SetLayout) Device->SetLayout( Device, Layout ); }
void GDS_SetDirty( struct GDS_Device* Device ) { Device->Dirty = true; }
int GDS_GetWidth( struct GDS_Device* Device ) { return Device ? Device->Width : 0; }
void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ) { GDS_CHECK_FOR_DEVICE(Device,return); Device->TextWidth = Device && TextWidth && TextWidth < Device->Width ? TextWidth : Device->Width; }
void GDS_SetTextWidth( struct GDS_Device* Device, int TextWidth ) { Device->TextWidth = Device && TextWidth && TextWidth < Device->Width ? TextWidth : Device->Width; }
int GDS_GetHeight( struct GDS_Device* Device ) { return Device ? Device->Height : 0; }
int GDS_GetDepth( struct GDS_Device* Device ) { return Device ? Device->Depth : 0; }
int GDS_GetMode( struct GDS_Device* Device ) { return Device ? Device->Mode : 0; }
void GDS_DisplayOn( struct GDS_Device* Device ) { if (Device && Device->DisplayOn) Device->DisplayOn( Device ); }
void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device && Device->DisplayOff) Device->DisplayOff( Device ); }
void GDS_DisplayOn( struct GDS_Device* Device ) { if (Device->DisplayOn) Device->DisplayOn( Device ); }
void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device->DisplayOff) Device->DisplayOff( Device ); }

View File

@@ -52,6 +52,5 @@ int GDS_GrayMap( struct GDS_Device* Device, uint8_t Level );
void GDS_ClearExt( struct GDS_Device* Device, bool full, ...);
void GDS_Clear( struct GDS_Device* Device, int Color );
void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color );
#define GDS_CHECK_FOR_DEVICE(dev,ret_act) if(!dev) ret_act
#endif

View File

@@ -62,6 +62,7 @@ static void register_free();
static void register_setdevicename();
static void register_heap();
static void register_dump_heap();
static void register_abort();
static void register_version();
static void register_restart();
#if CONFIG_WITH_CONFIG_UI
@@ -90,6 +91,7 @@ void register_system()
register_free();
register_heap();
register_dump_heap();
register_abort();
register_version();
register_restart();
register_factory_boot();
@@ -144,6 +146,27 @@ static void register_version()
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
/* 'abort' command */
static int cmd_abort(int argc, char **argv)
{
cmd_send_messaging(argv[0],MESSAGING_INFO,"ABORT!\r\n");
abort();
return 0;
}
static void register_abort()
{
const esp_console_cmd_t cmd = {
.command = "abort",
.help = "Crash now!",
.hint = NULL,
.func = &cmd_abort,
};
cmd_to_json(&cmd);
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
{
if(is_recovery_running){

View File

@@ -70,7 +70,7 @@ static char * get_dac_config_string(){
return config_alloc_get_str("dac_config", CONFIG_DAC_CONFIG, "model=i2s,bck=" STR(CONFIG_I2S_BCK_IO)
",ws=" STR(CONFIG_I2S_WS_IO) ",do=" STR(CONFIG_I2S_DO_IO)
",sda=" STR(CONFIG_I2C_SDA) ",scl=" STR(CONFIG_I2C_SCL)
",mute=" STR(CONFIG_MUTE_GPIO));
",mute=" STR(CONFIG_MUTE_GPIO) ",mck=" STR(CONFIG_I2S_MCK_IO));
}
/****************************************************************************************

View File

@@ -38,6 +38,7 @@ static esp_err_t actrls_process_action (const cJSON * member, actrls_config_t *c
static esp_err_t actrls_init_json(const char *profile_name, bool create);
static void control_rotary_handler(void *client, rotary_event_e event, bool long_press);
static void volume_rotary_handler(void *client, rotary_event_e event, bool long_press);
static void rotary_timer( TimerHandle_t xTimer );
static const actrls_config_map_t actrls_config_map[] =
@@ -157,6 +158,24 @@ esp_err_t actrls_init(const char *profile_name) {
err = create_rotary(NULL, A, B, SW, longpress, control_rotary_handler) ? ESP_OK : ESP_FAIL;
}
free(config);
config = config_alloc_get_default(NVS_TYPE_STR, "volume_rotary", NULL, 0);
// now see if we have a dedicated volume rotary
if (config && *config) {
int A = -1, B = -1, SW = -1;
// parse config
PARSE_PARAM(config, "A", '=', A);
PARSE_PARAM(config, "B", '=', B);
PARSE_PARAM(config, "SW", '=', SW);
// create rotary (no handling of long press)
err |= create_volume_rotary(NULL, A, B, SW, volume_rotary_handler) ? ESP_OK : ESP_FAIL;
}
free(config);
// set infrared GPIO if any
parse_set_GPIO(set_ir_gpio);
@@ -290,6 +309,29 @@ static void control_rotary_handler(void *client, rotary_event_e event, bool long
if (action != ACTRLS_NONE) (*current_controls[action])(pressed);
}
/****************************************************************************************
*
*/
static void volume_rotary_handler(void *client, rotary_event_e event, bool long_press) {
actrls_action_e action = ACTRLS_NONE;
bool pressed = true;
switch(event) {
case ROTARY_LEFT:
action = ACTRLS_VOLDOWN;
break;
case ROTARY_RIGHT:
action = ACTRLS_VOLUP;
break;
case ROTARY_PRESSED:
action = ACTRLS_TOGGLE;
default:
break;
}
if (action != ACTRLS_NONE) (*current_controls[action])(pressed);
}
/****************************************************************************************
*
*/
@@ -568,6 +610,13 @@ exit:
return err;
}
/****************************************************************************************
*
*/
actrls_handler get_ctrl_handler(actrls_action_e action) {
return current_controls[action];
}
/****************************************************************************************
*
*/

View File

@@ -53,3 +53,9 @@ void actrls_set_default(const actrls_t controls, bool raw_controls, actrls_hook_
void actrls_set(const actrls_t controls, bool raw_controls, actrls_hook_t *hook, actrls_ir_handler_t *ir_handler);
void actrls_unset(void);
bool actrls_ir_action(uint16_t addr, uint16_t code);
/* Call this to get the handler for any of the audio actions. It will map to the control specific
to the current mode (LMS, AirPlay, Spotify). This is useful if you have a custom way to create
buttons (like analogue buttons)
*/
actrls_handler get_ctrl_handler(actrls_action_e);

View File

@@ -58,13 +58,13 @@ static struct {
static TimerHandle_t polled_timer;
static EXT_RAM_ATTR struct {
static EXT_RAM_ATTR struct encoder {
QueueHandle_t queue;
void *client;
rotary_encoder_info_t info;
int A, B, SW;
rotary_handler handler;
} rotary;
} rotary, volume;
static EXT_RAM_ATTR struct {
RingbufHandle_t rb;
@@ -227,11 +227,22 @@ static void buttons_task(void* arg) {
// received a rotary event
xQueueReceive(rotary.queue, &event, 0);
ESP_LOGD(TAG, "Event: position %d, direction %s", event.state.position,
ESP_LOGD(TAG, "Rotary event: position %d, direction %s", event.state.position,
event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET");
rotary.handler(rotary.client, event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ?
ROTARY_RIGHT : ROTARY_LEFT, false);
} else if (xActivatedMember == volume.queue) {
rotary_encoder_event_t event = { 0 };
// received a volume rotary event
xQueueReceive(volume.queue, &event, 0);
ESP_LOGD(TAG, "Volume event: position %d, direction %s", event.state.position,
event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET");
volume.handler(volume.client, event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ?
ROTARY_RIGHT : ROTARY_LEFT, false);
} else {
// this is IR
active = infrared_receive(infrared.rb, infrared.handler);
@@ -395,7 +406,55 @@ void *button_remap(void *client, int gpio, button_handler handler, int long_pres
}
/****************************************************************************************
* Rotary encoder handler
* Create rotary encoder
*/
static bool create_rotary_encoder(struct encoder *encoder, void *id, int A, int B, int SW, int long_press, rotary_handler handler, button_handler button) {
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
if (A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) {
ESP_LOGI(TAG, "Cannot create rotary %d %d", A, B);
return false;
}
encoder->A = A;
encoder->B = B;
encoder->SW = SW;
encoder->client = id;
encoder->handler = handler;
// Initialise the rotary encoder device with the GPIOs for A and B signals
rotary_encoder_init(&encoder->info, A, B);
// Create a queue for events from the rotary encoder driver.
encoder->queue = rotary_encoder_create_queue();
rotary_encoder_set_queue(&encoder->info, encoder->queue);
common_task_init();
xQueueAddToSet( encoder->queue, common_queue_set );
// create companion button if rotary has a switch
if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, button, long_press, -1);
return true;
}
/****************************************************************************************
* Volume button encoder handler
*/
static void volume_button_handler(void *id, button_event_e event, button_press_e mode, bool long_press) {
ESP_LOGI(TAG, "Volume encoder push-button %d", event);
volume.handler(id, event == BUTTON_PRESSED ? ROTARY_PRESSED : ROTARY_RELEASED, long_press);
}
/****************************************************************************************
* Create volume encoder
*/
bool create_volume_rotary(void *id, int A, int B, int SW, rotary_handler handler) {
ESP_LOGI(TAG, "Created volume encoder A:%d B:%d, SW:%d", A, B, SW);
return create_rotary_encoder(&volume, id, A, B, SW, false, handler, volume_button_handler);
}
/****************************************************************************************
* Rotary button encoder handler
*/
static void rotary_button_handler(void *id, button_event_e event, button_press_e mode, bool long_press) {
ESP_LOGI(TAG, "Rotary push-button %d", event);
@@ -406,34 +465,8 @@ static void rotary_button_handler(void *id, button_event_e event, button_press_e
* Create rotary encoder
*/
bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handler handler) {
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
if (A == -1 || B == -1 || A == 36 || A == 39 || B == 36 || B == 39) {
ESP_LOGI(TAG, "Cannot create rotary %d %d", A, B);
return false;
}
rotary.A = A;
rotary.B = B;
rotary.SW = SW;
rotary.client = id;
rotary.handler = handler;
// Initialise the rotary encoder device with the GPIOs for A and B signals
rotary_encoder_init(&rotary.info, A, B);
// Create a queue for events from the rotary encoder driver.
rotary.queue = rotary_encoder_create_queue();
rotary_encoder_set_queue(&rotary.info, rotary.queue);
common_task_init();
xQueueAddToSet( rotary.queue, common_queue_set );
// create companion button if rotary has a switch
if (SW != -1) button_create(id, SW, BUTTON_LOW, true, 0, rotary_button_handler, long_press, -1);
ESP_LOGI(TAG, "Created rotary encoder A:%d B:%d, SW:%d", A, B, SW);
return true;
return create_rotary_encoder(&rotary, id, A, B, SW, long_press, handler, rotary_button_handler);
}
/****************************************************************************************

View File

@@ -34,5 +34,5 @@ typedef enum { ROTARY_LEFT, ROTARY_RIGHT, ROTARY_PRESSED, ROTARY_RELEASED } rota
typedef void (*rotary_handler)(void *id, rotary_event_e event, bool long_press);
bool create_rotary(void *id, int A, int B, int SW, int long_press, rotary_handler handler);
bool create_volume_rotary(void *id, int A, int B, int SW, rotary_handler handler);
bool create_infrared(int gpio, infrared_handler handler, infrared_mode_t mode);

View File

@@ -83,6 +83,10 @@ static void mcp23s17_set_direction(gpio_exp_t* self);
static uint32_t mcp23s17_read(gpio_exp_t* self);
static void mcp23s17_write(gpio_exp_t* self);
static void aw9523_set_direction(gpio_exp_t* self);
static uint32_t aw9523_read(gpio_exp_t* self);
static void aw9523_write(gpio_exp_t* self);
static void service_handler(void *arg);
static void debounce_handler( TimerHandle_t xTimer );
@@ -130,6 +134,11 @@ static const struct gpio_exp_model_s {
.set_pull_mode = mcp23s17_set_pull_mode,
.read = mcp23s17_read,
.write = mcp23s17_write, },
{ .model = "aw9523",
.trigger = GPIO_INTR_LOW_LEVEL,
.set_direction = aw9523_set_direction,
.read = aw9523_read,
.write = aw9523_write, },
};
static EXT_RAM_ATTR uint8_t n_expanders;
@@ -671,6 +680,24 @@ static void mcp23s17_write(gpio_exp_t* self) {
spi_write(self->spi_handle, self->phy.addr, 0x12, self->shadow, 2);
}
/****************************************************************************************
* AW9523 family : direction, read and write
*/
static void aw9523_set_direction(gpio_exp_t* self) {
i2c_write(self->phy.port, self->phy.addr, 0x04, self->r_mask, 2);
i2c_write(self->phy.port, self->phy.addr, 0x06, ~self->r_mask, 2);
}
static uint32_t aw9523_read(gpio_exp_t* self) {
// Reading both registers in one go does not seem to reset IRQ correctly
uint8_t port1 = i2c_read(self->phy.port, self->phy.addr, 0x00, 1);
return (i2c_read(self->phy.port, self->phy.addr, 0x01, 1) << 8) | port1;
}
static void aw9523_write(gpio_exp_t* self) {
i2c_write(self->phy.port, self->phy.addr, 0x02, self->shadow, 2);
}
/***************************************************************************************
I2C low level
***************************************************************************************/
@@ -793,4 +820,4 @@ static uint32_t spi_read(spi_device_handle_t handle, uint8_t addr, uint8_t reg,
free(transaction);
return data;
}
}

View File

@@ -248,7 +248,8 @@ void monitor_svc_init(void) {
// re-use button management for jack handler, it's a GPIO after all
if (jack.gpio != -1) {
ESP_LOGI(TAG,"Adding jack (%s) detection GPIO %d", jack.active ? "high" : "low", jack.gpio);
button_create(NULL, jack.gpio, jack.active ? BUTTON_HIGH : BUTTON_LOW, false, 250, jack_handler_default, 0, -1);
// Use GPIO pull so the line does not float (Muse jack detect is active-low and needs pull-up)
button_create(NULL, jack.gpio, jack.active ? BUTTON_HIGH : BUTTON_LOW, true, 250, jack_handler_default, 0, -1);
}
#ifdef CONFIG_SPKFAULT_GPIO_LEVEL
@@ -297,4 +298,4 @@ void monitor_svc_init(void) {
*/
monitor_gpio_t * get_jack_insertion_gpio(){
return &jack;
}
}

View File

@@ -21,6 +21,12 @@ set(BELL_DISABLE_MQTT ON)
set(BELL_DISABLE_WEBSERVER ON)
set(CSPOT_TARGET_ESP32 ON)
set(_secret $ENV{SPOTIFY_SECRET})
if(_secret)
separate_arguments(_secret)
set_source_files_properties(Shim.cpp PROPERTIES COMPILE_OPTIONS "${_secret}")
endif()
# because CMake is so broken, the cache set below overrides a normal "set" for the first build
set(BELL_EXTERNAL_VORBIS "idf::codecs" CACHE STRING "provide own codecs")
set(BELL_EXTERNAL_CJSON "idf::json" CACHE STRING "provide own CJSON")

View File

@@ -32,6 +32,16 @@
#include "platform_config.h"
#include "nvs_utilities.h"
#include "tools.h"
#if !defined(CLIENT_ID) || !defined(CLIENT_SECRET)
#if __has_include("client_info.h")
#include "client_info.h"
#else
#warning "missing Spotify's CLIENT_ID and/or CLIENT_SECRET (set SPOTIFY_SECRET env variable or set it in client_info.h)"
#define CLIENT_ID "<your client id>"
#define CLIENT_SECRET "<your client secret>"
#endif
#endif
static class cspotPlayer *player;
@@ -123,7 +133,7 @@ size_t cspotPlayer::pcmWrite(uint8_t *pcm, size_t bytes, std::string_view trackI
}
return dataHandler(pcm, bytes);
}
}
extern "C" {
static esp_err_t handleGET(httpd_req_t *request) {
@@ -365,6 +375,8 @@ void cspotPlayer::runTask() {
ctx->session->connectWithRandomAp();
ctx->config.authData = ctx->session->authenticate(blob);
ctx->config.clientId = CLIENT_ID;
ctx->config.clientSecret = CLIENT_SECRET;
// Auth successful
if (ctx->config.authData.size() > 0) {

View File

@@ -0,0 +1,4 @@
#pragma once
#define CLIENT_ID "<your spotify client's id>"
#define CLIENT_SECRET "<your spotify client's secret>"

View File

@@ -1,5 +1,6 @@
#include <cassert>
#include <vector>
#include <mutex>
#include "BellLogger.h"
#include "MDNSService.h"

View File

@@ -24,6 +24,8 @@ struct Context {
AudioFormat audioFormat = AudioFormat::AudioFormat_OGG_VORBIS_160;
std::string deviceId;
std::string deviceName;
std::string clientId;
std::string clientSecret;
std::vector<uint8_t> authData;
int volume;

View File

@@ -7,6 +7,7 @@
#include <vector> // for vector
#include "BellLogger.h" // for AbstractLogger
#include "BellUtils.h" // for BELL_SLEEP_MS
#include "CSpotContext.h" // for Context
#include "HTTPClient.h"
#include "Logger.h" // for CSPOT_LOG
@@ -24,13 +25,8 @@
#include "nlohmann/json_fwd.hpp" // for json
#endif
#include "protobuf/login5.pb.h" // for LoginRequest
using namespace cspot;
static std::string CLIENT_ID =
"65b708073fc0480ea92a077233ca87bd"; // Spotify web client's client id
static std::string SCOPES =
"streaming,user-library-read,user-library-modify,user-top-read,user-read-"
"recently-played"; // Required access scopes
@@ -68,69 +64,43 @@ void AccessKeyFetcher::updateAccessKey() {
keyPending = true;
// Prepare a protobuf login request
static LoginRequest loginRequest = LoginRequest_init_zero;
static LoginResponse loginResponse = LoginResponse_init_zero;
// Assign necessary request fields
loginRequest.client_info.client_id.funcs.encode = &bell::nanopb::encodeString;
loginRequest.client_info.client_id.arg = &CLIENT_ID;
loginRequest.client_info.device_id.funcs.encode = &bell::nanopb::encodeString;
loginRequest.client_info.device_id.arg = &ctx->config.deviceId;
loginRequest.login_method.stored_credential.username.funcs.encode =
&bell::nanopb::encodeString;
loginRequest.login_method.stored_credential.username.arg =
&ctx->config.username;
// Set login method to stored credential
loginRequest.which_login_method = LoginRequest_stored_credential_tag;
loginRequest.login_method.stored_credential.data.funcs.encode =
&bell::nanopb::encodeVector;
loginRequest.login_method.stored_credential.data.arg = &ctx->config.authData;
// Max retry of 3, can receive different hash cat types
int retryCount = 3;
bool success = false;
do {
auto encodedRequest = pbEncode(LoginRequest_fields, &loginRequest);
CSPOT_LOG(info, "Access token expired, fetching new one... %d",
encodedRequest.size());
CSPOT_LOG(info, "Access token expired, fetching new one...");
// Perform a login5 request, containing the encoded protobuf data
auto credentials = "grant_type=client_credentials&client_id=" + ctx->config.clientId + "&client_secret=" + ctx->config.clientSecret;
std::vector<uint8_t> body(credentials.begin(), credentials.end());
auto response = bell::HTTPClient::post(
"https://login5.spotify.com/v3/login",
{{"Content-Type", "application/x-protobuf"}}, encodedRequest);
auto responseBytes = response->bytes();
// Deserialize the response
pbDecode(loginResponse, LoginResponse_fields, responseBytes);
if (loginResponse.which_response == LoginResponse_ok_tag) {
// Successfully received an auth token
"https://accounts.spotify.com/api/token",
{ {"Content-Type", "application/x-www-form-urlencoded"} }, body);
#ifdef BELL_ONLY_CJSON
cJSON* root = cJSON_Parse(response->body().data());
if (!cJSON_GetObjectItem(root, "error")) {
accessKey = std::string(cJSON_GetObjectItem(root, "access_token")->valuestring);
int expiresIn = cJSON_GetObjectItem(root, "expires_in")->valueint;
cJSON_Delete(root);
#else
auto root = nlohmann::json::parse(response->bytes());
if (!root.contains("error")) {
accessKey = std::string(root["access_token"]);
int expiresIn = root["expires_in"];
#endif
// Successfully received an auth token
CSPOT_LOG(info, "Access token sucessfully fetched");
success = true;
accessKey = std::string(loginResponse.response.ok.access_token);
// Expire in ~30 minutes
int expiresIn = 3600 / 2;
if (loginResponse.response.ok.has_access_token_expires_in) {
int expiresIn = loginResponse.response.ok.access_token_expires_in / 2;
}
this->expiresAt =
ctx->timeProvider->getSyncedTimestamp() + (expiresIn * 1000);
} else {
CSPOT_LOG(error, "Failed to fetch access token");
ctx->timeProvider->getSyncedTimestamp() + (expiresIn * 1000);
}
else {
CSPOT_LOG(error, "Failed to fetch access token");
BELL_SLEEP_MS(3000);
}
// Free up allocated memory for response
pb_release(LoginResponse_fields, &loginResponse);
retryCount--;
} while (retryCount >= 0 && !success);

View File

@@ -687,6 +687,8 @@ void draw_VU(struct GDS_Device * display, int level, int x, int y, int width, bo
static void grfe_handler( u8_t *data, int len) {
struct grfe_packet *pkt = (struct grfe_packet*) data;
if (!display) return;
// we don't support transition, simply claim we're done
if (pkt->transition != 'c') {
LOG_INFO("Transition %c requested with offset %hu, param %d", pkt->transition, pkt->offset, pkt->param);
@@ -763,6 +765,8 @@ static void grfs_handler(u8_t *data, int len) {
int size = len - sizeof(struct grfs_packet);
int offset = htons(pkt->offset);
if (!display) return;
LOG_DEBUG("grfs s:%u d:%u p:%u sp:%u by:%hu m:%hu w:%hu o:%hu",
(int) pkt->screen,
(int) pkt->direction, // 1=left, 2=right
@@ -773,7 +777,7 @@ static void grfs_handler(u8_t *data, int len) {
htons(pkt->width), // last column of animation that contains a "full" screen
htons(pkt->offset) // offset if multiple packets are sent
);
// new grfs frame, build scroller info
if (!offset) {
// use the display as a general lock
@@ -818,6 +822,8 @@ static void grfs_handler(u8_t *data, int len) {
static void grfg_handler(u8_t *data, int len) {
struct grfg_packet *pkt = (struct grfg_packet*) data;
if (!display) return;
LOG_DEBUG("gfrg s:%hu w:%hu (len:%u)", htons(pkt->screen), htons(pkt->width), len);
// full screen artwork or for small screen, visu has priority when full screen
@@ -864,6 +870,8 @@ static void grfa_handler(u8_t *data, int len) {
int offset = htonl(pkt->offset);
int length = htonl(pkt->length);
if (!display) return;
// when using full screen visualizer on small screen there is a brief overlay
artwork.enable = (length != 0);

View File

@@ -22,7 +22,8 @@ static EXT_RAM_ATTR struct {
void *handle;
float loudness, volume;
uint32_t samplerate;
float gain[EQ_BANDS], loudness_gain[EQ_BANDS];
int8_t gain[EQ_BANDS];
float loudness_gain[EQ_BANDS];
bool update;
} equalizer;
@@ -151,6 +152,8 @@ void equalizer_set_gain(int8_t *gain) {
char config[EQ_BANDS * 4 + 1] = { };
int n = 0;
if (memcmp(equalizer.gain, gain, EQ_BANDS) != 0) equalizer.update = true;
for (int i = 0; i < EQ_BANDS; i++) {
equalizer.gain[i] = gain[i];
n += sprintf(config + n, "%d,", gain[i]);
@@ -159,9 +162,6 @@ void equalizer_set_gain(int8_t *gain) {
config[n-1] = '\0';
config_set_value(NVS_TYPE_STR, "equalizer", config);
// update only if something changed
if (!memcmp(equalizer.gain, gain, EQ_BANDS)) equalizer.update = true;
LOG_INFO("equalizer gain %s", config);
#else
LOG_INFO("no equalizer with 32 bits samples");

View File

@@ -222,6 +222,25 @@ static void set_i2s_pin(char *config, i2s_pin_config_t *pin_config) {
#endif
}
/* When a panic occurs during playback, the I2S interface can produce a loud noise burst.
* This code runs just before the system panic handler to "emergency stop" the I2S iterface
* to prevent the noise burst from happening. Note that when this code is called the system
* has already crashed, so no need to disable interrupts, acquire locks, or otherwise be nice.
*
* This code makes use of the linker --wrap feature to intercept the call to esp_panic_handler.
*/
void __real_esp_panic_handler(void*);
void __wrap_esp_panic_handler (void* info) {
esp_rom_printf("I2S abort!\r\n");
i2s_stop(CONFIG_I2S_NUM);
/* Call the original panic handler function to finish processing this error */
__real_esp_panic_handler(info);
}
/****************************************************************************************
* Initialize the DAC output
*/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -77,6 +77,12 @@ declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
@@ -235,6 +241,9 @@ declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare let sd: {};
declare let rf: boolean;
declare function refreshStatus(): void;

View File

@@ -1,5 +1,5 @@
target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.6d425ac534311a0131b2.css.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.3b0bbfde52d921a84f9b.css.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/favicon-32x32.png BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.29cc48.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.29cc48.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.3fded7.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.3fded7.bundle.js.gz BINARY)

View File

@@ -1,34 +1,34 @@
// Automatically generated. Do not edit manually!.
#include <inttypes.h>
extern const uint8_t _index_6d425ac534311a0131b2_css_gz_start[] asm("_binary_index_6d425ac534311a0131b2_css_gz_start");
extern const uint8_t _index_6d425ac534311a0131b2_css_gz_end[] asm("_binary_index_6d425ac534311a0131b2_css_gz_end");
extern const uint8_t _index_3b0bbfde52d921a84f9b_css_gz_start[] asm("_binary_index_3b0bbfde52d921a84f9b_css_gz_start");
extern const uint8_t _index_3b0bbfde52d921a84f9b_css_gz_end[] asm("_binary_index_3b0bbfde52d921a84f9b_css_gz_end");
extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_start");
extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
extern const uint8_t _index_29cc48_bundle_js_gz_start[] asm("_binary_index_29cc48_bundle_js_gz_start");
extern const uint8_t _index_29cc48_bundle_js_gz_end[] asm("_binary_index_29cc48_bundle_js_gz_end");
extern const uint8_t _node_vendors_29cc48_bundle_js_gz_start[] asm("_binary_node_vendors_29cc48_bundle_js_gz_start");
extern const uint8_t _node_vendors_29cc48_bundle_js_gz_end[] asm("_binary_node_vendors_29cc48_bundle_js_gz_end");
extern const uint8_t _index_3fded7_bundle_js_gz_start[] asm("_binary_index_3fded7_bundle_js_gz_start");
extern const uint8_t _index_3fded7_bundle_js_gz_end[] asm("_binary_index_3fded7_bundle_js_gz_end");
extern const uint8_t _node_vendors_3fded7_bundle_js_gz_start[] asm("_binary_node_vendors_3fded7_bundle_js_gz_start");
extern const uint8_t _node_vendors_3fded7_bundle_js_gz_end[] asm("_binary_node_vendors_3fded7_bundle_js_gz_end");
const char * resource_lookups[] = {
"/css/index.6d425ac534311a0131b2.css.gz",
"/css/index.3b0bbfde52d921a84f9b.css.gz",
"/favicon-32x32.png",
"/index.html.gz",
"/js/index.29cc48.bundle.js.gz",
"/js/node_vendors.29cc48.bundle.js.gz",
"/js/index.3fded7.bundle.js.gz",
"/js/node_vendors.3fded7.bundle.js.gz",
""
};
const uint8_t * resource_map_start[] = {
_index_6d425ac534311a0131b2_css_gz_start,
_index_3b0bbfde52d921a84f9b_css_gz_start,
_favicon_32x32_png_start,
_index_html_gz_start,
_index_29cc48_bundle_js_gz_start,
_node_vendors_29cc48_bundle_js_gz_start
_index_3fded7_bundle_js_gz_start,
_node_vendors_3fded7_bundle_js_gz_start
};
const uint8_t * resource_map_end[] = {
_index_6d425ac534311a0131b2_css_gz_end,
_index_3b0bbfde52d921a84f9b_css_gz_end,
_favicon_32x32_png_end,
_index_html_gz_end,
_index_29cc48_bundle_js_gz_end,
_node_vendors_29cc48_bundle_js_gz_end
_index_3fded7_bundle_js_gz_end,
_node_vendors_3fded7_bundle_js_gz_end
};

View File

@@ -1,6 +1,6 @@
/***********************************
webpack_headers
dist/css/index.6d425ac534311a0131b2.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.29cc48.bundle.js.gz,dist/js/node_vendors.29cc48.bundle.js.gz
dist/css/index.3b0bbfde52d921a84f9b.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.3fded7.bundle.js.gz,dist/js/node_vendors.3fded7.bundle.js.gz
***********************************/
#pragma once
#include <inttypes.h>

View File

@@ -129,7 +129,7 @@ menu "Squeezelite-ESP32"
config DAC_CONTROLSET
string
default "{ \"init\": [ {\"reg\":41, \"val\":128}, {\"reg\":18, \"val\":255} ], \"poweron\": [ {\"reg\":18, \"val\":64, \"mode\":\"or\"} ], \"poweroff\": [ {\"reg\":18, \"val\":191, \"mode\":\"and\"} ] }" if TWATCH2020
default "{\"init\":[ {\"reg\":0,\"val\":128}, {\"reg\":0,\"val\":0}, {\"reg\":25,\"val\":4}, {\"reg\":1,\"val\":80}, {\"reg\":2,\"val\":0}, {\"reg\":8,\"val\":0}, {\"reg\":4,\"val\":192}, {\"reg\":0,\"val\":18}, {\"reg\":1,\"val\":0}, {\"reg\":23,\"val\":24}, {\"reg\":24,\"val\":2}, {\"reg\":38,\"val\":9}, {\"reg\":39,\"val\":144}, {\"reg\":42,\"val\":144}, {\"reg\":43,\"val\":128}, {\"reg\":45,\"val\":128}, {\"reg\":27,\"val\":0}, {\"reg\":26,\"val\":0}, {\"reg\":2,\"val\":240}, {\"reg\":2,\"val\":0}, {\"reg\":29,\"val\":28}, {\"reg\":4,\"val\":48}, {\"reg\":25,\"val\":0}, {\"reg\":46,\"val\":33}, {\"reg\":47,\"val\":33} ]}" if MUSE
default "{\"init\":[ {\"reg\":0,\"val\":128}, {\"reg\":0,\"val\":0}, {\"reg\":25,\"val\":4}, {\"reg\":1,\"val\":80}, {\"reg\":2,\"val\":0}, {\"reg\":8,\"val\":0}, {\"reg\":4,\"val\":192}, {\"reg\":0,\"val\":18}, {\"reg\":1,\"val\":0}, {\"reg\":23,\"val\":24}, {\"reg\":24,\"val\":2}, {\"reg\":38,\"val\":9}, {\"reg\":39,\"val\":144}, {\"reg\":42,\"val\":144}, {\"reg\":43,\"val\":128}, {\"reg\":45,\"val\":128}, {\"reg\":27,\"val\":0}, {\"reg\":26,\"val\":0}, {\"reg\":2,\"val\":240}, {\"reg\":2,\"val\":0}, {\"reg\":29,\"val\":28}, {\"reg\":4,\"val\":60}, {\"reg\":25,\"val\":0}, {\"reg\":46,\"val\":33}, {\"reg\":47,\"val\":33} , {\"reg\":48,\"val\":33}, {\"reg\":49,\"val\":33}]}" if MUSE
default ""
config AUDIO_CONTROLS
string
@@ -153,7 +153,8 @@ menu "Squeezelite-ESP32"
default -1
config JACK_GPIO
int
default 34 if SQUEEZEAMP || MUSE
default 27 if MUSE
default 34 if SQUEEZEAMP
default -1
config SPKFAULT_GPIO
int
@@ -369,6 +370,12 @@ menu "Squeezelite-ESP32"
help
Set GPIO for rotary encoder (quadrature phase). See README on SqueezeESP32 project's GitHub for more details
A=<gpio>,B=<gpio>[,SW=gpio>[[,knobonly[=<ms>]|[,volume][,longpress]]
config VOLUME_ROTARY_ENCODER
string "Volume Rotary Encoder configuration"
default ""
help
Set GPIO for volume rotary encoder (quadrature phase). See README on SqueezeESP32 project's GitHub for more details
A=<gpio>,B=<gpio>[,SW=gpio>]
config GPIO_EXP_CONFIG
string "GPIO expander configuration"
help
@@ -457,4 +464,4 @@ menu "Squeezelite-ESP32"
default "squeezelite -o I2S -b 500:2000 -d all=info -C 30"
help
This is the command to run when starting the device
endmenu
endmenu

View File

@@ -89,6 +89,7 @@ const DefaultStringVal defaultStringVals[] = {
{"actrls_config", ""},
{"lms_ctrls_raw", "n"},
{"rotary_config", CONFIG_ROTARY_ENCODER},
{"volume_rotary", CONFIG_VOLUME_ROTARY_ENCODER},
{"display_config", CONFIG_DISPLAY_CONFIG},
{"eth_config", CONFIG_ETH_CONFIG},
{"i2c_config", CONFIG_I2C_CONFIG},
@@ -114,6 +115,7 @@ const DefaultStringVal defaultStringVals[] = {
{"dhcp_tmout", "8"},
{"target", CONFIG_TARGET},
{"led_vu_config", ""},
{"autoexec", "1"},
#ifdef CONFIG_BT_SINK
{"bt_sink_pin", STR(CONFIG_BT_SINK_PIN)},
{"bt_sink_volume", "127"},
@@ -123,11 +125,10 @@ const DefaultStringVal defaultStringVals[] = {
{"a2dp_ctmt", STR(CONFIG_A2DP_CONNECT_TIMEOUT_MS)},
{"a2dp_ctrld", STR(CONFIG_A2DP_CONTROL_DELAY_MS)},
{"a2dp_sink_name", CONFIG_A2DP_SINK_NAME},
{"autoexec", "1"},
#endif
#ifdef CONFIG_AIRPLAY_SINK
{"airplay_port", CONFIG_AIRPLAY_PORT},
{"enable_airplay", STR(CONFIG_AIRPLAY_SINK)}
#endif
#endif
};
static bool bNetworkConnected=false;

Binary file not shown.

View File

@@ -220,7 +220,8 @@ sub send_equalizer {
sub send_loudness {
my ($client, $loudness) = @_;
$loudness ||= $prefs->client($client)->get('loudness') || 0;
$loudness //= $prefs->client($client)->get('loudness');
my $data = pack("c1", $loudness);
$client->sendFrame( loud => \$data );
}

View File

@@ -10,6 +10,6 @@
<name>PLUGIN_SQUEEZEESP32</name>
<description>PLUGIN_SQUEEZEESP32_DESC</description>
<module>Plugins::SqueezeESP32::Plugin</module>
<version>0.600</version>
<version>0.601</version>
<creator>Philippe</creator>
</extensions>

View File

@@ -1,10 +1,10 @@
<?xml version='1.0' standalone='yes'?>
<extensions>
<plugins>
<plugin version="0.600" name="SqueezeESP32" minTarget="7.9" maxTarget="*">
<plugin version="0.601" name="SqueezeESP32" minTarget="7.9" maxTarget="*">
<link>https://github.com/sle118/squeezelite-esp32</link>
<creator>Philippe</creator>
<sha>335b585e22eddbddacce00f34001d8bf2ee0f54f</sha>
<sha>439637e01db7410157a333446cd284509f877849</sha>
<email>philippe_44@outlook.com</email>
<desc lang="EN">SqueezeESP32 additional player id (100/101)</desc>
<url>http://raw.githubusercontent.com/sle118/squeezelite-esp32/master-v4.3/plugin/SqueezeESP32.zip</url>

View File

@@ -1,28 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEyDCCA7CgAwIBAgIQDPW9BitWAvR6uFAsI8zwZjANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0yMTAzMzAwMDAwMDBaFw0zMTAzMjkyMzU5NTlaMFkxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMzAxBgNVBAMTKkRpZ2lDZXJ0IEdsb2Jh
bCBHMiBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMz3EGJPprtjb+2QUlbFbSd7ehJWivH0+dbn4Y+9lavyYEEV
cNsSAPonCrVXOFt9slGTcZUOakGUWzUb+nv6u8W+JDD+Vu/E832X4xT1FE3LpxDy
FuqrIvAxIhFhaZAmunjZlx/jfWardUSVc8is/+9dCopZQ+GssjoP80j812s3wWPc
3kbW20X+fSP9kOhRBx5Ro1/tSUZUfyyIxfQTnJcVPAPooTncaQwywa8WV0yUR0J8
osicfebUTVSvQpmowQTCd5zWSOTOEeAqgJnwQ3DPP3Zr0UxJqyRewg2C/Uaoq2yT
zGJSQnWS+Jr6Xl6ysGHlHx+5fwmY6D36g39HaaECAwEAAaOCAYIwggF+MBIGA1Ud
EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHSFgMBmx9833s+9KTeqAx2+7c0XMB8G
A1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA4GA1UdDwEB/wQEAwIBhjAd
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYIKwYBBQUHAQEEajBoMCQG
CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQAYIKwYBBQUHMAKG
NGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RH
Mi5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29t
L0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDA9BgNVHSAENjA0MAsGCWCGSAGG/WwC
ATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgGBmeBDAECAzANBgkqhkiG
9w0BAQsFAAOCAQEAkPFwyyiXaZd8dP3A+iZ7U6utzWX9upwGnIrXWkOH7U1MVl+t
wcW1BSAuWdH/SvWgKtiwla3JLko716f2b4gp/DA/JIS7w7d7kwcsr4drdjPtAFVS
slme5LnQ89/nD/7d+MS5EHKBCQRfz5eeLjJ1js+aWNJXMX43AYGyZm0pGrFmCW3R
bpD0ufovARTFXFZkAdl9h6g4U5+LXUZtXMYnhIHUfoyMo5tS58aI7Dd8KvvwVVo4
chDYABPPTHPbqjc1qCmBaZx2vN4Ye5DUys/vZwP9BFohFrH/6j/f3IL16/RZkiMN
JCqVJUzKoZHm1Lesh3Sz8W2jmdv51b2EQJ8HmA==
-----END CERTIFICATE-----

View File

@@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBjzELMAkGA1UEBhMCR0IxGzAZBgNV
BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE
ChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFJTQSBEb21haW4g
VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA1nMz1tc8INAA0hdFuNY+B6I/x0HuMjDJsGz99J/LEpgPLT+N
TQEMgg8Xf2Iu6bhIefsWg06t1zIlk7cHv7lQP6lMw0Aq6Tn/2YHKHxYyQdqAJrkj
eocgHuP/IJo8lURvh3UGkEC0MpMWCRAIIz7S3YcPb11RFGoKacVPAXJpz9OTTG0E
oKMbgn6xmrntxZ7FN3ifmgg0+1YuWMQJDgZkW7w33PGfKGioVrCSo1yfu4iYCBsk
Haswha6vsC6eep3BwEIc4gLw6uBK0u+QDrTBQBbwb4VCSmT3pDCg/r8uoydajotY
uK3DGReEY+1vVv2Dy2A0xHS+5p3b4eTlygxfFQIDAQABo4IBbjCCAWowHwYDVR0j
BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFI2MXsRUrYrhd+mb
+ZsF4bgBjWHhMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAbBgNVHSAEFDASMAYGBFUdIAAw
CAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0
LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2Bggr
BgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNv
bS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDov
L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMr9hvQ5Iw0/H
ukdN+Jx4GQHcEx2Ab/zDcLRSmjEzmldS+zGea6TvVKqJjUAXaPgREHzSyrHxVYbH
7rM2kYb2OVG/Rr8PoLq0935JxCo2F57kaDl6r5ROVm+yezu/Coa9zcV3HAO4OLGi
H19+24rcRki2aArPsrW04jTkZ6k4Zgle0rj8nSg6F0AnwnJOKf0hPHzPE/uWLMUx
RP0T7dWbqWlod3zu4f+k+TY4CFM5ooQ0nBnzvg6s1SQ36yOoeNDT5++SR2RiOSLv
xvcRviKFxmZEJCaOEDKNyJOuB56DPi/Z+fVGjmO+wea03KbNIaiGCpXZLoUmGv38
sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
-----END CERTIFICATE-----

Binary file not shown.

View File

@@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFgTCCBGmgAwIBAgIQOXJEOvkit1HX02wQ3TE1lTANBgkqhkiG9w0BAQwFADB7
MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
VQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UE
AwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTE5MDMxMjAwMDAwMFoXDTI4
MTIzMTIzNTk1OVowgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5
MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBO
ZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0
aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgBJlFzYOw9sI
s9CsVw127c0n00ytUINh4qogTQktZAnczomfzD2p7PbPwdzx07HWezcoEStH2jnG
vDoZtF+mvX2do2NCtnbyqTsrkfjib9DsFiCQCT7i6HTJGLSR1GJk23+jBvGIGGqQ
Ijy8/hPwhxR79uQfjtTkUcYRZ0YIUcuGFFQ/vDP+fmyc/xadGL1RjjWmp2bIcmfb
IWax1Jt4A8BQOujM8Ny8nkz+rwWWNR9XWrf/zvk9tyy29lTdyOcSOk2uTIq3XJq0
tyA9yn8iNK5+O2hmAUTnAU5GU5szYPeUvlM3kHND8zLDU+/bqv50TmnHa4xgk97E
xwzf4TKuzJM7UXiVZ4vuPVb+DNBpDxsP8yUmazNt925H+nND5X4OpWaxKXwyhGNV
icQNwZNUMBkTrNN9N6frXTpsNVzbQdcS2qlJC9/YgIoJk2KOtWbPJYjNhLixP6Q5
D9kCnusSTJV882sFqV4Wg8y4Z+LoE53MW4LTTLPtW//e5XOsIzstAL81VXQJSdhJ
WBp/kjbmUZIO8yZ9HE0XvMnsQybQv0FfQKlERPSZ51eHnlAfV1SoPv10Yy+xUGUJ
5lhCLkMaTLTwJUdZ+gQek9QmRkpQgbLevni3/GcV4clXhB4PY9bpYrrWX1Uu6lzG
KAgEJTm4Diup8kyXHAc/DVL17e8vgg8CAwEAAaOB8jCB7zAfBgNVHSMEGDAWgBSg
EQojPpbxB+zirynvgqV/0DCktDAdBgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rID
ZsswDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAG
BgRVHSAAMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29t
L0FBQUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggr
BgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUA
A4IBAQAYh1HcdCE9nIrgJ7cz0C7M7PDmy14R3iJvm3WOnnL+5Nb+qh+cli3vA0p+
rvSNb3I8QzvAP+u431yqqcau8vzY7qN7Q/aGNnwU4M309z/+3ri0ivCRlv79Q2R+
/czSAaF9ffgZGclCKxO/WIu6pKJmBHaIkU4MiRTOok3JMrO66BQavHHxW/BBC5gA
CiIDEOUMsfnNkjcZ7Tvx5Dq2+UUTJnWvu6rvP3t3O9LEApE9GQDTF1w52z97GA1F
zZOFli9d31kWTz9RvdVFGD/tSo7oBmF0Ixa1DVBzJ0RHfxBdiSprhTEUxOipakyA
vGp4z7h/jnZymQyd/teRCBaho1+V
-----END CERTIFICATE-----

View File

@@ -1,27 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEozCCBEmgAwIBAgIQTij3hrZsGjuULNLEDrdCpTAKBggqhkjOPQQDAjCBjzEL
MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
BxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5T
ZWN0aWdvIEVDQyBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMB4X
DTI0MDMwNzAwMDAwMFoXDTI1MDMwNzIzNTk1OVowFTETMBEGA1UEAxMKZ2l0aHVi
LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABARO/Ho9XdkY1qh9mAgjOUkW
mXTb05jgRulKciMVBuKB3ZHexvCdyoiCRHEMBfFXoZhWkQVMogNLo/lW215X3pGj
ggL+MIIC+jAfBgNVHSMEGDAWgBT2hQo7EYbhBH0Oqgss0u7MZHt7rjAdBgNVHQ4E
FgQUO2g/NDr1RzTK76ZOPZq9Xm56zJ8wDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB
/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEkGA1UdIARCMEAw
NAYLKwYBBAGyMQECAgcwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNv
bS9DUFMwCAYGZ4EMAQIBMIGEBggrBgEFBQcBAQR4MHYwTwYIKwYBBQUHMAKGQ2h0
dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb0VDQ0RvbWFpblZhbGlkYXRpb25T
ZWN1cmVTZXJ2ZXJDQS5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3Rp
Z28uY29tMIIBgAYKKwYBBAHWeQIEAgSCAXAEggFsAWoAdwDPEVbu1S58r/OHW9lp
LpvpGnFnSrAX7KwB0lt3zsw7CAAAAY4WOvAZAAAEAwBIMEYCIQD7oNz/2oO8VGaW
WrqrsBQBzQH0hRhMLm11oeMpg1fNawIhAKWc0q7Z+mxDVYV/6ov7f/i0H/aAcHSC
Ii/QJcECraOpAHYAouMK5EXvva2bfjjtR2d3U9eCW4SU1yteGyzEuVCkR+cAAAGO
Fjrv+AAABAMARzBFAiEAyupEIVAMk0c8BVVpF0QbisfoEwy5xJQKQOe8EvMU4W8C
IGAIIuzjxBFlHpkqcsa7UZy24y/B6xZnktUw/Ne5q5hCAHcATnWjJ1yaEMM4W2zU
3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGOFjrv9wAABAMASDBGAiEA+8OvQzpgRf31
uLBsCE8ktCUfvsiRT7zWSqeXliA09TUCIQDcB7Xn97aEDMBKXIbdm5KZ9GjvRyoF
9skD5/4GneoMWzAlBgNVHREEHjAcggpnaXRodWIuY29tgg53d3cuZ2l0aHViLmNv
bTAKBggqhkjOPQQDAgNIADBFAiEAru2McPr0eNwcWNuDEY0a/rGzXRfRrm+6XfZe
SzhYZewCIBq4TUEBCgapv7xvAtRKdVdi/b4m36Uyej1ggyJsiesA
MIIEoTCCBEigAwIBAgIRAKtmhrVie+gFloITMBKGSfUwCgYIKoZIzj0EAwIwgY8x
CzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNV
BAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UEAxMu
U2VjdGlnbyBFQ0MgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTAe
Fw0yNTAyMDUwMDAwMDBaFw0yNjAyMDUyMzU5NTlaMBUxEzARBgNVBAMTCmdpdGh1
Yi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQgNFxG/yzL+CSarvC7L3ep
H5chNnG6wiYYxR5D/Z1J4MxGnIX8KbT5fCgLoyzHXL9v50bdBIq6y4AtN4gN7gbW
o4IC/DCCAvgwHwYDVR0jBBgwFoAU9oUKOxGG4QR9DqoLLNLuzGR7e64wHQYDVR0O
BBYEFFPIf96emE7HTda83quVPjA9PdHIMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB
Af8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBJBgNVHSAEQjBA
MDQGCysGAQQBsjEBAgIHMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5j
b20vQ1BTMAgGBmeBDAECATCBhAYIKwYBBQUHAQEEeDB2ME8GCCsGAQUFBzAChkNo
dHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29FQ0NEb21haW5WYWxpZGF0aW9u
U2VjdXJlU2VydmVyQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0
aWdvLmNvbTCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHUAlpdkv1VYl633Q4do
NwhCd+nwOtX2pPM2bkakPw/KqcYAAAGU02uUSwAABAMARjBEAiA7i6o+LpQjt6Ae
EjltHhs/TiECnHd0xTeer/3vD1xgsAIgYlGwRot+SqEBCs//frx/YHTPwox9QLdy
7GjTLWHfcMAAdwAZhtTHKKpv/roDb3gqTQGRqs4tcjEPrs5dcEEtJUzH1AAAAZTT
a5PtAAAEAwBIMEYCIQDlrInx7J+3MfqgxB2+Fvq3dMlk1qj4chOw/+HkYVfG0AIh
AMT+JKAQfUuIdBGxfryrGrwsOD3pRs1tyAyykdPGRgsTAHYAyzj3FYl8hKFEX1vB
3fvJbvKaWc1HCmkFhbDLFMMUWOcAAAGU02uUJQAABAMARzBFAiEA1GKW92agDFNJ
IYrMH3gaJdXsdIVpUcZOfxH1FksbuLECIFJCfslINhc53Q0TIMJHdcFOW2tgG4tB
A1dL881tXbMnMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29t
MAoGCCqGSM49BAMCA0cAMEQCIHGMp27BBBJ1356lCe2WYyzYIp/fAONQM3AkeE/f
ym0sAiBtVfN3YgIZ+neHEfwcRhhz4uDpc8F+tKmtceWJSicMkA==
-----END CERTIFICATE-----

View File

@@ -1,54 +1,4 @@
-----BEGIN CERTIFICATE-----
MIIEyDCCA7CgAwIBAgIQDPW9BitWAvR6uFAsI8zwZjANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0yMTAzMzAwMDAwMDBaFw0zMTAzMjkyMzU5NTlaMFkxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMzAxBgNVBAMTKkRpZ2lDZXJ0IEdsb2Jh
bCBHMiBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMz3EGJPprtjb+2QUlbFbSd7ehJWivH0+dbn4Y+9lavyYEEV
cNsSAPonCrVXOFt9slGTcZUOakGUWzUb+nv6u8W+JDD+Vu/E832X4xT1FE3LpxDy
FuqrIvAxIhFhaZAmunjZlx/jfWardUSVc8is/+9dCopZQ+GssjoP80j812s3wWPc
3kbW20X+fSP9kOhRBx5Ro1/tSUZUfyyIxfQTnJcVPAPooTncaQwywa8WV0yUR0J8
osicfebUTVSvQpmowQTCd5zWSOTOEeAqgJnwQ3DPP3Zr0UxJqyRewg2C/Uaoq2yT
zGJSQnWS+Jr6Xl6ysGHlHx+5fwmY6D36g39HaaECAwEAAaOCAYIwggF+MBIGA1Ud
EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHSFgMBmx9833s+9KTeqAx2+7c0XMB8G
A1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA4GA1UdDwEB/wQEAwIBhjAd
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYIKwYBBQUHAQEEajBoMCQG
CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQAYIKwYBBQUHMAKG
NGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RH
Mi5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29t
L0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDA9BgNVHSAENjA0MAsGCWCGSAGG/WwC
ATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgGBmeBDAECAzANBgkqhkiG
9w0BAQsFAAOCAQEAkPFwyyiXaZd8dP3A+iZ7U6utzWX9upwGnIrXWkOH7U1MVl+t
wcW1BSAuWdH/SvWgKtiwla3JLko716f2b4gp/DA/JIS7w7d7kwcsr4drdjPtAFVS
slme5LnQ89/nD/7d+MS5EHKBCQRfz5eeLjJ1js+aWNJXMX43AYGyZm0pGrFmCW3R
bpD0ufovARTFXFZkAdl9h6g4U5+LXUZtXMYnhIHUfoyMo5tS58aI7Dd8KvvwVVo4
chDYABPPTHPbqjc1qCmBaZx2vN4Ye5DUys/vZwP9BFohFrH/6j/f3IL16/RZkiMN
JCqVJUzKoZHm1Lesh3Sz8W2jmdv51b2EQJ8HmA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDqDCCAy6gAwIBAgIRAPNkTmtuAFAjfglGvXvh9R0wCgYIKoZIzj0EAwMwgYgx
CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz
ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQD
@@ -71,6 +21,41 @@ cS0chWBNKPFNpvDKdrdKRe+oAkr2jU+ubgIxAODheSr2XhcA7oz9HmedGdMhlrd9
4ToKFbZl+/OnFFzqnvOhcjHvClECEQcKmc8fmA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBjzELMAkGA1UEBhMCR0IxGzAZBgNV
BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE
ChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFJTQSBEb21haW4g
VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA1nMz1tc8INAA0hdFuNY+B6I/x0HuMjDJsGz99J/LEpgPLT+N
TQEMgg8Xf2Iu6bhIefsWg06t1zIlk7cHv7lQP6lMw0Aq6Tn/2YHKHxYyQdqAJrkj
eocgHuP/IJo8lURvh3UGkEC0MpMWCRAIIz7S3YcPb11RFGoKacVPAXJpz9OTTG0E
oKMbgn6xmrntxZ7FN3ifmgg0+1YuWMQJDgZkW7w33PGfKGioVrCSo1yfu4iYCBsk
Haswha6vsC6eep3BwEIc4gLw6uBK0u+QDrTBQBbwb4VCSmT3pDCg/r8uoydajotY
uK3DGReEY+1vVv2Dy2A0xHS+5p3b4eTlygxfFQIDAQABo4IBbjCCAWowHwYDVR0j
BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFI2MXsRUrYrhd+mb
+ZsF4bgBjWHhMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAbBgNVHSAEFDASMAYGBFUdIAAw
CAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0
LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2Bggr
BgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNv
bS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDov
L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMr9hvQ5Iw0/H
ukdN+Jx4GQHcEx2Ab/zDcLRSmjEzmldS+zGea6TvVKqJjUAXaPgREHzSyrHxVYbH
7rM2kYb2OVG/Rr8PoLq0935JxCo2F57kaDl6r5ROVm+yezu/Coa9zcV3HAO4OLGi
H19+24rcRki2aArPsrW04jTkZ6k4Zgle0rj8nSg6F0AnwnJOKf0hPHzPE/uWLMUx
RP0T7dWbqWlod3zu4f+k+TY4CFM5ooQ0nBnzvg6s1SQ36yOoeNDT5++SR2RiOSLv
xvcRviKFxmZEJCaOEDKNyJOuB56DPi/Z+fVGjmO+wea03KbNIaiGCpXZLoUmGv38
sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID0zCCArugAwIBAgIQVmcdBOpPmUxvEIFHWdJ1lDANBgkqhkiG9w0BAQwFADB7
MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
VQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UE
@@ -94,116 +79,144 @@ CV4Ks2dH/hzg1cEo70qLRDEmBDeNiXQ2Lu+lIg+DdEmSx/cQwgwp+7e9un/jX9Wf
8qn0dNW44bOwgeThpWOjzOoEeJBuv/c=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEozCCBEmgAwIBAgIQTij3hrZsGjuULNLEDrdCpTAKBggqhkjOPQQDAjCBjzEL
MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
BxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5T
ZWN0aWdvIEVDQyBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMB4X
DTI0MDMwNzAwMDAwMFoXDTI1MDMwNzIzNTk1OVowFTETMBEGA1UEAxMKZ2l0aHVi
LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABARO/Ho9XdkY1qh9mAgjOUkW
mXTb05jgRulKciMVBuKB3ZHexvCdyoiCRHEMBfFXoZhWkQVMogNLo/lW215X3pGj
ggL+MIIC+jAfBgNVHSMEGDAWgBT2hQo7EYbhBH0Oqgss0u7MZHt7rjAdBgNVHQ4E
FgQUO2g/NDr1RzTK76ZOPZq9Xm56zJ8wDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB
/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEkGA1UdIARCMEAw
NAYLKwYBBAGyMQECAgcwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNv
bS9DUFMwCAYGZ4EMAQIBMIGEBggrBgEFBQcBAQR4MHYwTwYIKwYBBQUHMAKGQ2h0
dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb0VDQ0RvbWFpblZhbGlkYXRpb25T
ZWN1cmVTZXJ2ZXJDQS5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3Rp
Z28uY29tMIIBgAYKKwYBBAHWeQIEAgSCAXAEggFsAWoAdwDPEVbu1S58r/OHW9lp
LpvpGnFnSrAX7KwB0lt3zsw7CAAAAY4WOvAZAAAEAwBIMEYCIQD7oNz/2oO8VGaW
WrqrsBQBzQH0hRhMLm11oeMpg1fNawIhAKWc0q7Z+mxDVYV/6ov7f/i0H/aAcHSC
Ii/QJcECraOpAHYAouMK5EXvva2bfjjtR2d3U9eCW4SU1yteGyzEuVCkR+cAAAGO
Fjrv+AAABAMARzBFAiEAyupEIVAMk0c8BVVpF0QbisfoEwy5xJQKQOe8EvMU4W8C
IGAIIuzjxBFlHpkqcsa7UZy24y/B6xZnktUw/Ne5q5hCAHcATnWjJ1yaEMM4W2zU
3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGOFjrv9wAABAMASDBGAiEA+8OvQzpgRf31
uLBsCE8ktCUfvsiRT7zWSqeXliA09TUCIQDcB7Xn97aEDMBKXIbdm5KZ9GjvRyoF
9skD5/4GneoMWzAlBgNVHREEHjAcggpnaXRodWIuY29tgg53d3cuZ2l0aHViLmNv
bTAKBggqhkjOPQQDAgNIADBFAiEAru2McPr0eNwcWNuDEY0a/rGzXRfRrm+6XfZe
SzhYZewCIBq4TUEBCgapv7xvAtRKdVdi/b4m36Uyej1ggyJsiesA
MIIFgTCCBGmgAwIBAgIQOXJEOvkit1HX02wQ3TE1lTANBgkqhkiG9w0BAQwFADB7
MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
VQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UE
AwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTE5MDMxMjAwMDAwMFoXDTI4
MTIzMTIzNTk1OVowgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5
MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBO
ZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0
aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgBJlFzYOw9sI
s9CsVw127c0n00ytUINh4qogTQktZAnczomfzD2p7PbPwdzx07HWezcoEStH2jnG
vDoZtF+mvX2do2NCtnbyqTsrkfjib9DsFiCQCT7i6HTJGLSR1GJk23+jBvGIGGqQ
Ijy8/hPwhxR79uQfjtTkUcYRZ0YIUcuGFFQ/vDP+fmyc/xadGL1RjjWmp2bIcmfb
IWax1Jt4A8BQOujM8Ny8nkz+rwWWNR9XWrf/zvk9tyy29lTdyOcSOk2uTIq3XJq0
tyA9yn8iNK5+O2hmAUTnAU5GU5szYPeUvlM3kHND8zLDU+/bqv50TmnHa4xgk97E
xwzf4TKuzJM7UXiVZ4vuPVb+DNBpDxsP8yUmazNt925H+nND5X4OpWaxKXwyhGNV
icQNwZNUMBkTrNN9N6frXTpsNVzbQdcS2qlJC9/YgIoJk2KOtWbPJYjNhLixP6Q5
D9kCnusSTJV882sFqV4Wg8y4Z+LoE53MW4LTTLPtW//e5XOsIzstAL81VXQJSdhJ
WBp/kjbmUZIO8yZ9HE0XvMnsQybQv0FfQKlERPSZ51eHnlAfV1SoPv10Yy+xUGUJ
5lhCLkMaTLTwJUdZ+gQek9QmRkpQgbLevni3/GcV4clXhB4PY9bpYrrWX1Uu6lzG
KAgEJTm4Diup8kyXHAc/DVL17e8vgg8CAwEAAaOB8jCB7zAfBgNVHSMEGDAWgBSg
EQojPpbxB+zirynvgqV/0DCktDAdBgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rID
ZsswDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAG
BgRVHSAAMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29t
L0FBQUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggr
BgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUA
A4IBAQAYh1HcdCE9nIrgJ7cz0C7M7PDmy14R3iJvm3WOnnL+5Nb+qh+cli3vA0p+
rvSNb3I8QzvAP+u431yqqcau8vzY7qN7Q/aGNnwU4M309z/+3ri0ivCRlv79Q2R+
/czSAaF9ffgZGclCKxO/WIu6pKJmBHaIkU4MiRTOok3JMrO66BQavHHxW/BBC5gA
CiIDEOUMsfnNkjcZ7Tvx5Dq2+UUTJnWvu6rvP3t3O9LEApE9GQDTF1w52z97GA1F
zZOFli9d31kWTz9RvdVFGD/tSo7oBmF0Ixa1DVBzJ0RHfxBdiSprhTEUxOipakyA
vGp4z7h/jnZymQyd/teRCBaho1+V
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIHOTCCBiGgAwIBAgIQBj1JF0BNOeUTyz/uzRsuGzANBgkqhkiG9w0BAQsFADBZ
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTMwMQYDVQQDEypE
aWdpQ2VydCBHbG9iYWwgRzIgVExTIFJTQSBTSEEyNTYgMjAyMCBDQTEwHhcNMjQw
MzE1MDAwMDAwWhcNMjUwMzE0MjM1OTU5WjBnMQswCQYDVQQGEwJVUzETMBEGA1UE
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMM
R2l0SHViLCBJbmMuMRQwEgYDVQQDDAsqLmdpdGh1Yi5pbzCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAK0rFKU6TEGvuLCY3ZOuXlG+3jerD6EP1gc1qe35
g68FqyGuVPOUddYNZiymjYMZxywoNp3qxlbFFBTf9etsayavT+uW+2UMjqCotAdK
KicBEspuExoACFuNgTi7sSUT7A55+k4/+5O+VtpaxQ5dmQk7HxcqvMYx5owBU+fB
wYDD+hXeg3YvxLZNeIlN8OlqWL8w9HbG+3ccegVEjOJQbkrcrW7IQMq2Uk92XjxI
PmMVIvaefqcC1poGYvS4VvEh3x64vJK1hEM4YLMKBaE/hqFtcMozi+H/8JqTCfzP
Qhnu21HIop9rSucxxnZbe9AeHz2LERpUTf3rjgOMg9PB1RUCAwEAAaOCA+0wggPp
MB8GA1UdIwQYMBaAFHSFgMBmx9833s+9KTeqAx2+7c0XMB0GA1UdDgQWBBTob1fr
hlGY65+lvlPa25SsKC777TB7BgNVHREEdDByggsqLmdpdGh1Yi5pb4IJZ2l0aHVi
LmlvghVnaXRodWJ1c2VyY29udGVudC5jb22CDnd3dy5naXRodWIuY29tggwqLmdp
dGh1Yi5jb22CFyouZ2l0aHVidXNlcmNvbnRlbnQuY29tggpnaXRodWIuY29tMD4G
A1UdIAQ3MDUwMwYGZ4EMAQICMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGln
aWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH
AwEGCCsGAQUFBwMCMIGfBgNVHR8EgZcwgZQwSKBGoESGQmh0dHA6Ly9jcmwzLmRp
Z2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbEcyVExTUlNBU0hBMjU2MjAyMENBMS0x
LmNybDBIoEagRIZCaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xv
YmFsRzJUTFNSU0FTSEEyNTYyMDIwQ0ExLTEuY3JsMIGHBggrBgEFBQcBAQR7MHkw
JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBRBggrBgEFBQcw
AoZFaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsRzJU
TFNSU0FTSEEyNTYyMDIwQ0ExLTEuY3J0MAwGA1UdEwEB/wQCMAAwggF/BgorBgEE
AdZ5AgQCBIIBbwSCAWsBaQB2AE51oydcmhDDOFts1N8/Uusd8OCOG41pwLH6ZLFi
mjnfAAABjkN89oAAAAQDAEcwRQIgU/M527Wcx0KQ3II7kCuG5WMuOHRSxKkf1xAj
JuSkyPACIQCVX0uurcIA2Ug7ipNN2S1ZygukWqJCh7hjIH0XsrXh8QB2AH1ZHhLh
eCp7HGFnfF79+NCHXBSgTpWeuQMv2Q6MLnm4AAABjkN89oEAAAQDAEcwRQIgCxpL
BDak+TWKarrCHlZn4DlqwEfAN3lvlgSo21HQuU8CIQDicrb72c0lA2suMWPWT92P
FLaRvFrFn9HVzI6Vh50YZgB3AObSMWNAd4zBEEEG13G5zsHSQPaWhIb7uocyHf0e
N45QAAABjkN89pQAAAQDAEgwRgIhAPJQX4QArFCjM0sKKzsWLmqmmU8lMhKEYR2T
ges1AQyQAiEA2Y3VhP5RG+dapcbwYgVbrTlgWzO7KE/lg1x11CVcz3QwDQYJKoZI
hvcNAQELBQADggEBAHKlvzObJBxxgyLaUNCEFf37mNFsUtXmaWvkmcfIt9V+TZ7Q
mtvjx5bsd5lqAflp/eqk4+JYpnYcKWrZfM/vMdxPQTeh/VQWewY/hYn6X/V1s2JI
MtjqEkW4aotVdWjHVvsx4rAjz5vtub/wVYgtrU8jusH3TVpT9/0AoFhKE5m2IS7M
Ig7wKR+DDxoNj4fFFluxteVNgbtwuJcb23NkBQqfHXCvQWqxXZZA4Nwl/WoGPoGG
dW5qVOc3BlhtITW53ASyhvKC7HArhj7LwQH8C/dRgn1agIHP9vVJ1NaZnPXhK98T
ohv++OO0E/F/bVGNWVnLBQ4v5PjQzRQUTGvM2mU=
MIIEoTCCBEigAwIBAgIRAKtmhrVie+gFloITMBKGSfUwCgYIKoZIzj0EAwIwgY8x
CzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNV
BAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UEAxMu
U2VjdGlnbyBFQ0MgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTAe
Fw0yNTAyMDUwMDAwMDBaFw0yNjAyMDUyMzU5NTlaMBUxEzARBgNVBAMTCmdpdGh1
Yi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQgNFxG/yzL+CSarvC7L3ep
H5chNnG6wiYYxR5D/Z1J4MxGnIX8KbT5fCgLoyzHXL9v50bdBIq6y4AtN4gN7gbW
o4IC/DCCAvgwHwYDVR0jBBgwFoAU9oUKOxGG4QR9DqoLLNLuzGR7e64wHQYDVR0O
BBYEFFPIf96emE7HTda83quVPjA9PdHIMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB
Af8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBJBgNVHSAEQjBA
MDQGCysGAQQBsjEBAgIHMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5j
b20vQ1BTMAgGBmeBDAECATCBhAYIKwYBBQUHAQEEeDB2ME8GCCsGAQUFBzAChkNo
dHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29FQ0NEb21haW5WYWxpZGF0aW9u
U2VjdXJlU2VydmVyQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0
aWdvLmNvbTCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHUAlpdkv1VYl633Q4do
NwhCd+nwOtX2pPM2bkakPw/KqcYAAAGU02uUSwAABAMARjBEAiA7i6o+LpQjt6Ae
EjltHhs/TiECnHd0xTeer/3vD1xgsAIgYlGwRot+SqEBCs//frx/YHTPwox9QLdy
7GjTLWHfcMAAdwAZhtTHKKpv/roDb3gqTQGRqs4tcjEPrs5dcEEtJUzH1AAAAZTT
a5PtAAAEAwBIMEYCIQDlrInx7J+3MfqgxB2+Fvq3dMlk1qj4chOw/+HkYVfG0AIh
AMT+JKAQfUuIdBGxfryrGrwsOD3pRs1tyAyykdPGRgsTAHYAyzj3FYl8hKFEX1vB
3fvJbvKaWc1HCmkFhbDLFMMUWOcAAAGU02uUJQAABAMARzBFAiEA1GKW92agDFNJ
IYrMH3gaJdXsdIVpUcZOfxH1FksbuLECIFJCfslINhc53Q0TIMJHdcFOW2tgG4tB
A1dL881tXbMnMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29t
MAoGCCqGSM49BAMCA0cAMEQCIHGMp27BBBJ1356lCe2WYyzYIp/fAONQM3AkeE/f
ym0sAiBtVfN3YgIZ+neHEfwcRhhz4uDpc8F+tKmtceWJSicMkA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIIPDCCBySgAwIBAgIQCoUc0xRNvf782dBaZzL1GDANBgkqhkiG9w0BAQsFADA8
MIIGhTCCBW2gAwIBAgIRAJB3NEFHMW75lZl2eur98bkwDQYJKoZIhvcNAQELBQAw
gY8xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UE
AxMuU2VjdGlnbyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
QTAeFw0yNTAzMDcwMDAwMDBaFw0yNjAzMDcyMzU5NTlaMBYxFDASBgNVBAMMCyou
Z2l0aHViLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxKQLElVm
JYKnZ9dmKMWrb4fy4BWFm658EQemS4hJgrt+1NFpL2tGVaFupVyV3vmKorCX3zej
c7+gH8Ugpemmj9r5tk1NZ0SXXALTjvT2i03oSqjwCzkn+R1o0TYg+G7PyQ5pE18A
E+K3VUcpch1f5RyBTEvE4+HUg4/6OpAIYFVznJ3yk8a+bo1i/HBp2MbtPzssSlT8
mPLY76SETtKdwgIdY91MkTiJd1x0KJDM2GPKM7pNTc81NMSw6WBzsxg4PFbR+BCY
82/sYu8iMy/AdYcUz72hh2DGXnVypzzV/LLgJ/VAP5m+md0lVH5KIG/cduDrajlo
LQ4LKJktO4VmwQIDAQABo4IDUjCCA04wHwYDVR0jBBgwFoAUjYxexFStiuF36Zv5
mwXhuAGNYeEwHQYDVR0OBBYEFBLwftAxb+SvNbWJ+0LZ7bcLk80EMA4GA1UdDwEB
/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
BQcDAjBJBgNVHSAEQjBAMDQGCysGAQQBsjEBAgIHMCUwIwYIKwYBBQUHAgEWF2h0
dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeBDAECATCBhAYIKwYBBQUHAQEEeDB2
ME8GCCsGAQUFBzAChkNodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29SU0FE
b21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCMGCCsGAQUFBzABhhdo
dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFo
AHYAlpdkv1VYl633Q4doNwhCd+nwOtX2pPM2bkakPw/KqcYAAAGVbeysdQAABAMA
RzBFAiEA+YIgsAqb2cqQVlF4JP2ERIVCH3RXdB7DjIPc6Ch5aK4CIHjqUoV7F5Mk
fcIQcmdn7Z5UR8nYtPA2OLvYc3mCFcLuAHcAGYbUxyiqb/66A294Kk0BkarOLXIx
D67OXXBBLSVMx9QAAAGVbeysDgAABAMASDBGAiEAjryAbXlHsXj/v4f7CWXJzDUX
SUuvA5kRH3doh4WPUQcCIQC+nojCqhCn/ZupbnI50O1T3FSKBQu/LOZ33fApzLJW
hQB1AMs49xWJfIShRF9bwd37yW7ymlnNRwppBYWwyxTDFFjnAAABlW3srDcAAAQD
AEYwRAIgS98L1D2W8nzV3tIQ0R4UJWxwxb7I/TT6e9ly0nA0QsACIFpl7s/WA1Qm
z1Vm8ZtihoNFubO/AiiaVGaeDQiznHFCMHsGA1UdEQR0MHKCCyouZ2l0aHViLmlv
ggwqLmdpdGh1Yi5jb22CFyouZ2l0aHVidXNlcmNvbnRlbnQuY29tggpnaXRodWIu
Y29tgglnaXRodWIuaW+CFWdpdGh1YnVzZXJjb250ZW50LmNvbYIOd3d3LmdpdGh1
Yi5jb20wDQYJKoZIhvcNAQELBQADggEBAHksjTVCptW9CtbBXu+7J2cDDmKRz/EA
kUyONuojOnKoI3d2f5DQDkqzu/gSj6B28YO3a4EYFktvwq3KnXAu9KzSM1ehlhtA
lxlvjjGUgXvux7DjnBH40ItKiE723opeWVbm2WExdRPSckm/CDwshz2U3Sl3M3Wt
v0xPuZJrg1tMIL58RqrS5PpFlAIIlEUC6dr+xVQrwLNcYXVVgvZsRSX/YbrzboLM
gWhuDSQPcaeDGHcy7NxRZHmlpHz+/Ot067VuxjGqm9veKNGZMUdroS+ocxAJBXv3
Z1NCCowvpZazNxKccQg7izYwd6HL70WMxCWFU0e70uw9KZqteG7SVcQ=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIIOzCCByOgAwIBAgIQCHNhNIH5XVH5G3SANwHecTANBgkqhkiG9w0BAQsFADA8
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
UlNBIDIwNDggTTAxMB4XDTI0MDIwODAwMDAwMFoXDTI1MDExMTIzNTk1OVowGzEZ
UlNBIDIwNDggTTAxMB4XDTI1MDkxOTAwMDAwMFoXDTI2MDgyMzIzNTk1OVowGzEZ
MBcGA1UEAxMQczMuYW1hem9uYXdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBALwJqC+8pyil6exbAjVQQF7gCYVso0DkcF26ZUwAd7YMSSLDeeRD
tmJkAq42fVbwgnaCsrCIguG2hwNxyD74jIuFY2hDQIjQN1q4kPVuXzAGJ/Ovys+C
TYyeNoKwYAt40D1Cs7gcFetvf26fdanJAdfgwnXKNDqWi9U7re/gA1XMqlezPHs8
rNPNm+cGYNLAtpHyeES6CIBLHL3lchDSxgK5myhFYDdIevMg4X/1j1YdEl7QzMj5
G34hJqEfqPDDOQlvWBW/rCd3xfjOcYyjPB0mGmY2XTVukQiD2Gruvhg7AW7QXsai
dHfn3RmSQ8zniuRvvziAjEunZuActUH8lKkCAwEAAaOCBVkwggVVMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBSczB3nSKDvmULmm/oN
oj26JpG8ojCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
LmFtYXpvbmF3cy5jb22CJiouczMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25h
d3MuY29tgiRzMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CHCou
czMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CGnMzLnVzLWVhc3QtMS5hbWF6b25h
d3MuY29tgiQqLnMzLWNvbnRyb2wudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CInMz
LWNvbnRyb2wudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLiouczMtY29udHJvbC5k
dWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLHMzLWNvbnRyb2wuZHVh
bHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgigqLnMzLWFjY2Vzc3BvaW50
LnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgjIqLnMzLWFjY2Vzc3BvaW50LmR1YWxz
dGFjay51cy1lYXN0LTEuYW1hem9uYXdzLmNvbYInKi5zMy1kZXByZWNhdGVkLnVz
LWVhc3QtMS5hbWF6b25hd3MuY29tgiVzMy1kZXByZWNhdGVkLnVzLWVhc3QtMS5h
bWF6b25hd3MuY29tghtzMy1leHRlcm5hbC0xLmFtYXpvbmF3cy5jb22CHSouczMt
ZXh0ZXJuYWwtMS5hbWF6b25hd3MuY29tghtzMy1leHRlcm5hbC0yLmFtYXpvbmF3
cy5jb22CHSouczMtZXh0ZXJuYWwtMi5hbWF6b25hd3MuY29tMBMGA1UdIAQMMAow
ADCCAQoCggEBAMdxOeavAJSP5sHcShN1qqDR2LF9RtWaXtp5bdgNNKlgt4buDh3f
EGe60xX+RNSANTeyWtUZ8fhtQ7ugj7OoMZi+a2KczPFj3Q34OgM/8+290Z9joZ0p
wkKNwY03qEO6vlr9E/qA0Y9A6xZBD6QNUmD7jR4Etqq7jtBFgocdjZ6bgMqGQ8Uh
Ss5qapqokrKQrbKZLBHKRCqYGoKwgD1ciXiV6iXuJj+GXDmwte7MZAfFyg5OJngh
GKNCMdU38AYRGrfTWoVH5RC67JlfZMenQBK9sB/XnrB3kOkRbBR/spRYsZg+mbaR
Q7uyPL0hTHyDu1KAe8BpmxYoDrvkmkLPr58CAwEAAaOCBVgwggVUMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBSLsv8vDlH1xvXIpmJ3
htLYjcrMszCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
LmFtYXpvbmF3cy5jb22CKCouczMtYWNjZXNzcG9pbnQudXMtZWFzdC0xLmFtYXpv
bmF3cy5jb22CJCouczMtY29udHJvbC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbYIk
czMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgicqLnMzLWRlcHJl
Y2F0ZWQudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLHMzLWNvbnRyb2wuZHVhbHN0
YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgh0qLnMzLWV4dGVybmFsLTIuYW1h
em9uYXdzLmNvbYIaczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CMiouczMtYWNj
ZXNzcG9pbnQuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tghwqLnMz
LnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgh0qLnMzLWV4dGVybmFsLTEuYW1hem9u
YXdzLmNvbYImKi5zMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22C
G3MzLWV4dGVybmFsLTIuYW1hem9uYXdzLmNvbYIiczMtY29udHJvbC51cy1lYXN0
LTEuYW1hem9uYXdzLmNvbYIbczMtZXh0ZXJuYWwtMS5hbWF6b25hd3MuY29tgiVz
My1kZXByZWNhdGVkLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgi4qLnMzLWNvbnRy
b2wuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tMBMGA1UdIAQMMAow
CAYGZ4EMAQIBMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
KwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5yMm0wMS5hbWF6
b250cnVzdC5jb20vcjJtMDEuY3JsMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw
AYYhaHR0cDovL29jc3AucjJtMDEuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC
hipodHRwOi8vY3J0LnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5jZXIwDAYD
VR0TAQH/BAIwADCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHcATnWjJ1yaEMM4
W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGNiq0a7AAABAMASDBGAiEAudzKuZ93
XwCkNvsOtCfkpgKu8egAFdXeCG6CPI+muiQCIQDGHiAYvh59sW14WsNF1gX6Wu1A
7JOtTemHgdTsFwmIdAB1AD8XS0/XIkdYlB1lHIS+DRLtkDd/H4Vq68G/KIXs+GRu
AAABjYqtGuwAAAQDAEYwRAIgGECWncBSVe5FGWQ5qgOotqodK6f2dTLwCjQqy3zp
QuACIHPLNnOXzyO8cxbe9iEy1ZWqdh2bqWqMtHUEx4kIY7awAHYAVYHUwhaQNgFK
6gubVzxT8MDkOHhwJQgXL6OqHQcT0wwAAAGNiq0begAABAMARzBFAiBi1XBFN0j+
SJ5PBCByXcJ8xP5anjWJRyuMdK6EkiDzZgIhAKaUpLPdOdiUxx9Xlar4tPz7Bnyw
bx0UFNyiSzPjD6i+MA0GCSqGSIb3DQEBCwUAA4IBAQCtvdXGbz9xJEg9DAPIlfRH
KE2pta2NMLObOqydPjkUFL9dOdgwAxHib9x6X3oTb5PDGqR7DZ5zyf8kdY/UN+nH
3h3WifDXrE2NlVBJ1NwABJ2ZFg2A0G9uchLc0wAvsl86ziQETHWqff7wlGrN5bek
HItY6nc90BH+Jk9nbTa66DMLw26V443hKLcGdq8Fu/N8VING5cw/yMg9HN0tKaZy
o4z9hbT4W12zwCyPPBLxoboTzJY0yTPUYdDbW1b1QIssj/BKwgm0Tfkm6V/MMnqs
BluqB+8VNGPJNhO0zoAI9TMIf2s0MElDyR08ABjvUjy00Gn/g0ZHXSWPEP+NQLoM
VR0TAQH/BAIwADCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHYA2AlVO5RPev/I
FhlvlE+Fq7D4/F6HVSYPFdEucrtFSxQAAAGZY2zFywAABAMARzBFAiEA52TfXblf
xGMn7zs62yXq7rXB/ccKutSfyoReVaLtluACIFL9G5g8WzioAe/Tmx0cJjYXBzof
9go+a5TjVIY4bpnnAHYAwjF+V0UZo0XufzjespBB68fCIVoiv3/Vta12mtkOUs0A
AAGZY2zFywAABAMARzBFAiAdPbpyBei1fmph20ZWi1ZN7nl9b6EDX0s/gYxduL7k
CQIhAMeQp4B56jeit+b3akK3MHyTQoZBgR2CZMBZI6QVk5DUAHUAlE5Dh/rswe+B
8xkkJqgYZQHH0184AgE/cmd9VTcuGdgAAAGZY2zF4AAABAMARjBEAiBpEesssZJD
0SnUOe2Alz/5nGHs/Usxgzgz/xrMmEAXwAIgI90hHJajlzg30MZC3RKkXV8wezmC
pK+h+FLlSvMOUVowDQYJKoZIhvcNAQELBQADggEBAMMItDbq4GvNzuM8t2iBx90Z
F0hcsivxMOHbbxvBRrLtEYjY5wyvmGdWF2t24YFaYzyEMb0qX0YLxLGpoJCf5vIJ
olRHHgdDdkxg354SVQ4+SB1SvpJlAjyzqAGD4XQHAU3t0+jK+9OfJp8Zh57Z3jzI
zhA5ILi5hT3mW3hbHaNfvDpiauB6Sm9T0jc7853Msuh17LvABsIYlt2gVx48ivJc
oLmsInswJM2kWvD8WGTc0sG0wQfT6GNxEGG9anP3odTgdPUNnm8OKqW8nabzmhfu
sMKmxp3ShPpT0KiO5gBlGsMkDKu0+xKB0QjGaRoRbFC/9f0if9jQX5Hiz/xxpS4=
-----END CERTIFICATE-----

View File

@@ -1,41 +1,37 @@
-----BEGIN CERTIFICATE-----
MIIHOTCCBiGgAwIBAgIQBj1JF0BNOeUTyz/uzRsuGzANBgkqhkiG9w0BAQsFADBZ
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTMwMQYDVQQDEypE
aWdpQ2VydCBHbG9iYWwgRzIgVExTIFJTQSBTSEEyNTYgMjAyMCBDQTEwHhcNMjQw
MzE1MDAwMDAwWhcNMjUwMzE0MjM1OTU5WjBnMQswCQYDVQQGEwJVUzETMBEGA1UE
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMM
R2l0SHViLCBJbmMuMRQwEgYDVQQDDAsqLmdpdGh1Yi5pbzCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAK0rFKU6TEGvuLCY3ZOuXlG+3jerD6EP1gc1qe35
g68FqyGuVPOUddYNZiymjYMZxywoNp3qxlbFFBTf9etsayavT+uW+2UMjqCotAdK
KicBEspuExoACFuNgTi7sSUT7A55+k4/+5O+VtpaxQ5dmQk7HxcqvMYx5owBU+fB
wYDD+hXeg3YvxLZNeIlN8OlqWL8w9HbG+3ccegVEjOJQbkrcrW7IQMq2Uk92XjxI
PmMVIvaefqcC1poGYvS4VvEh3x64vJK1hEM4YLMKBaE/hqFtcMozi+H/8JqTCfzP
Qhnu21HIop9rSucxxnZbe9AeHz2LERpUTf3rjgOMg9PB1RUCAwEAAaOCA+0wggPp
MB8GA1UdIwQYMBaAFHSFgMBmx9833s+9KTeqAx2+7c0XMB0GA1UdDgQWBBTob1fr
hlGY65+lvlPa25SsKC777TB7BgNVHREEdDByggsqLmdpdGh1Yi5pb4IJZ2l0aHVi
LmlvghVnaXRodWJ1c2VyY29udGVudC5jb22CDnd3dy5naXRodWIuY29tggwqLmdp
dGh1Yi5jb22CFyouZ2l0aHVidXNlcmNvbnRlbnQuY29tggpnaXRodWIuY29tMD4G
A1UdIAQ3MDUwMwYGZ4EMAQICMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGln
aWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH
AwEGCCsGAQUFBwMCMIGfBgNVHR8EgZcwgZQwSKBGoESGQmh0dHA6Ly9jcmwzLmRp
Z2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbEcyVExTUlNBU0hBMjU2MjAyMENBMS0x
LmNybDBIoEagRIZCaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xv
YmFsRzJUTFNSU0FTSEEyNTYyMDIwQ0ExLTEuY3JsMIGHBggrBgEFBQcBAQR7MHkw
JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBRBggrBgEFBQcw
AoZFaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsRzJU
TFNSU0FTSEEyNTYyMDIwQ0ExLTEuY3J0MAwGA1UdEwEB/wQCMAAwggF/BgorBgEE
AdZ5AgQCBIIBbwSCAWsBaQB2AE51oydcmhDDOFts1N8/Uusd8OCOG41pwLH6ZLFi
mjnfAAABjkN89oAAAAQDAEcwRQIgU/M527Wcx0KQ3II7kCuG5WMuOHRSxKkf1xAj
JuSkyPACIQCVX0uurcIA2Ug7ipNN2S1ZygukWqJCh7hjIH0XsrXh8QB2AH1ZHhLh
eCp7HGFnfF79+NCHXBSgTpWeuQMv2Q6MLnm4AAABjkN89oEAAAQDAEcwRQIgCxpL
BDak+TWKarrCHlZn4DlqwEfAN3lvlgSo21HQuU8CIQDicrb72c0lA2suMWPWT92P
FLaRvFrFn9HVzI6Vh50YZgB3AObSMWNAd4zBEEEG13G5zsHSQPaWhIb7uocyHf0e
N45QAAABjkN89pQAAAQDAEgwRgIhAPJQX4QArFCjM0sKKzsWLmqmmU8lMhKEYR2T
ges1AQyQAiEA2Y3VhP5RG+dapcbwYgVbrTlgWzO7KE/lg1x11CVcz3QwDQYJKoZI
hvcNAQELBQADggEBAHKlvzObJBxxgyLaUNCEFf37mNFsUtXmaWvkmcfIt9V+TZ7Q
mtvjx5bsd5lqAflp/eqk4+JYpnYcKWrZfM/vMdxPQTeh/VQWewY/hYn6X/V1s2JI
MtjqEkW4aotVdWjHVvsx4rAjz5vtub/wVYgtrU8jusH3TVpT9/0AoFhKE5m2IS7M
Ig7wKR+DDxoNj4fFFluxteVNgbtwuJcb23NkBQqfHXCvQWqxXZZA4Nwl/WoGPoGG
dW5qVOc3BlhtITW53ASyhvKC7HArhj7LwQH8C/dRgn1agIHP9vVJ1NaZnPXhK98T
ohv++OO0E/F/bVGNWVnLBQ4v5PjQzRQUTGvM2mU=
MIIGhTCCBW2gAwIBAgIRAJB3NEFHMW75lZl2eur98bkwDQYJKoZIhvcNAQELBQAw
gY8xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UE
AxMuU2VjdGlnbyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
QTAeFw0yNTAzMDcwMDAwMDBaFw0yNjAzMDcyMzU5NTlaMBYxFDASBgNVBAMMCyou
Z2l0aHViLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxKQLElVm
JYKnZ9dmKMWrb4fy4BWFm658EQemS4hJgrt+1NFpL2tGVaFupVyV3vmKorCX3zej
c7+gH8Ugpemmj9r5tk1NZ0SXXALTjvT2i03oSqjwCzkn+R1o0TYg+G7PyQ5pE18A
E+K3VUcpch1f5RyBTEvE4+HUg4/6OpAIYFVznJ3yk8a+bo1i/HBp2MbtPzssSlT8
mPLY76SETtKdwgIdY91MkTiJd1x0KJDM2GPKM7pNTc81NMSw6WBzsxg4PFbR+BCY
82/sYu8iMy/AdYcUz72hh2DGXnVypzzV/LLgJ/VAP5m+md0lVH5KIG/cduDrajlo
LQ4LKJktO4VmwQIDAQABo4IDUjCCA04wHwYDVR0jBBgwFoAUjYxexFStiuF36Zv5
mwXhuAGNYeEwHQYDVR0OBBYEFBLwftAxb+SvNbWJ+0LZ7bcLk80EMA4GA1UdDwEB
/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
BQcDAjBJBgNVHSAEQjBAMDQGCysGAQQBsjEBAgIHMCUwIwYIKwYBBQUHAgEWF2h0
dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeBDAECATCBhAYIKwYBBQUHAQEEeDB2
ME8GCCsGAQUFBzAChkNodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29SU0FE
b21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCMGCCsGAQUFBzABhhdo
dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFo
AHYAlpdkv1VYl633Q4doNwhCd+nwOtX2pPM2bkakPw/KqcYAAAGVbeysdQAABAMA
RzBFAiEA+YIgsAqb2cqQVlF4JP2ERIVCH3RXdB7DjIPc6Ch5aK4CIHjqUoV7F5Mk
fcIQcmdn7Z5UR8nYtPA2OLvYc3mCFcLuAHcAGYbUxyiqb/66A294Kk0BkarOLXIx
D67OXXBBLSVMx9QAAAGVbeysDgAABAMASDBGAiEAjryAbXlHsXj/v4f7CWXJzDUX
SUuvA5kRH3doh4WPUQcCIQC+nojCqhCn/ZupbnI50O1T3FSKBQu/LOZ33fApzLJW
hQB1AMs49xWJfIShRF9bwd37yW7ymlnNRwppBYWwyxTDFFjnAAABlW3srDcAAAQD
AEYwRAIgS98L1D2W8nzV3tIQ0R4UJWxwxb7I/TT6e9ly0nA0QsACIFpl7s/WA1Qm
z1Vm8ZtihoNFubO/AiiaVGaeDQiznHFCMHsGA1UdEQR0MHKCCyouZ2l0aHViLmlv
ggwqLmdpdGh1Yi5jb22CFyouZ2l0aHVidXNlcmNvbnRlbnQuY29tggpnaXRodWIu
Y29tgglnaXRodWIuaW+CFWdpdGh1YnVzZXJjb250ZW50LmNvbYIOd3d3LmdpdGh1
Yi5jb20wDQYJKoZIhvcNAQELBQADggEBAHksjTVCptW9CtbBXu+7J2cDDmKRz/EA
kUyONuojOnKoI3d2f5DQDkqzu/gSj6B28YO3a4EYFktvwq3KnXAu9KzSM1ehlhtA
lxlvjjGUgXvux7DjnBH40ItKiE723opeWVbm2WExdRPSckm/CDwshz2U3Sl3M3Wt
v0xPuZJrg1tMIL58RqrS5PpFlAIIlEUC6dr+xVQrwLNcYXVVgvZsRSX/YbrzboLM
gWhuDSQPcaeDGHcy7NxRZHmlpHz+/Ot067VuxjGqm9veKNGZMUdroS+ocxAJBXv3
Z1NCCowvpZazNxKccQg7izYwd6HL70WMxCWFU0e70uw9KZqteG7SVcQ=
-----END CERTIFICATE-----

BIN
server_certs/r2m01.cer.52 Normal file

Binary file not shown.

BIN
server_certs/r2m01.cer.53 Normal file

Binary file not shown.

BIN
server_certs/r2m01.cer.54 Normal file

Binary file not shown.

BIN
server_certs/r2m01.cer.55 Normal file

Binary file not shown.

View File

@@ -1,46 +1,46 @@
-----BEGIN CERTIFICATE-----
MIIIPDCCBySgAwIBAgIQCoUc0xRNvf782dBaZzL1GDANBgkqhkiG9w0BAQsFADA8
MIIIOzCCByOgAwIBAgIQCHNhNIH5XVH5G3SANwHecTANBgkqhkiG9w0BAQsFADA8
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
UlNBIDIwNDggTTAxMB4XDTI0MDIwODAwMDAwMFoXDTI1MDExMTIzNTk1OVowGzEZ
UlNBIDIwNDggTTAxMB4XDTI1MDkxOTAwMDAwMFoXDTI2MDgyMzIzNTk1OVowGzEZ
MBcGA1UEAxMQczMuYW1hem9uYXdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBALwJqC+8pyil6exbAjVQQF7gCYVso0DkcF26ZUwAd7YMSSLDeeRD
tmJkAq42fVbwgnaCsrCIguG2hwNxyD74jIuFY2hDQIjQN1q4kPVuXzAGJ/Ovys+C
TYyeNoKwYAt40D1Cs7gcFetvf26fdanJAdfgwnXKNDqWi9U7re/gA1XMqlezPHs8
rNPNm+cGYNLAtpHyeES6CIBLHL3lchDSxgK5myhFYDdIevMg4X/1j1YdEl7QzMj5
G34hJqEfqPDDOQlvWBW/rCd3xfjOcYyjPB0mGmY2XTVukQiD2Gruvhg7AW7QXsai
dHfn3RmSQ8zniuRvvziAjEunZuActUH8lKkCAwEAAaOCBVkwggVVMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBSczB3nSKDvmULmm/oN
oj26JpG8ojCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
LmFtYXpvbmF3cy5jb22CJiouczMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25h
d3MuY29tgiRzMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CHCou
czMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CGnMzLnVzLWVhc3QtMS5hbWF6b25h
d3MuY29tgiQqLnMzLWNvbnRyb2wudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CInMz
LWNvbnRyb2wudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLiouczMtY29udHJvbC5k
dWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLHMzLWNvbnRyb2wuZHVh
bHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgigqLnMzLWFjY2Vzc3BvaW50
LnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgjIqLnMzLWFjY2Vzc3BvaW50LmR1YWxz
dGFjay51cy1lYXN0LTEuYW1hem9uYXdzLmNvbYInKi5zMy1kZXByZWNhdGVkLnVz
LWVhc3QtMS5hbWF6b25hd3MuY29tgiVzMy1kZXByZWNhdGVkLnVzLWVhc3QtMS5h
bWF6b25hd3MuY29tghtzMy1leHRlcm5hbC0xLmFtYXpvbmF3cy5jb22CHSouczMt
ZXh0ZXJuYWwtMS5hbWF6b25hd3MuY29tghtzMy1leHRlcm5hbC0yLmFtYXpvbmF3
cy5jb22CHSouczMtZXh0ZXJuYWwtMi5hbWF6b25hd3MuY29tMBMGA1UdIAQMMAow
ADCCAQoCggEBAMdxOeavAJSP5sHcShN1qqDR2LF9RtWaXtp5bdgNNKlgt4buDh3f
EGe60xX+RNSANTeyWtUZ8fhtQ7ugj7OoMZi+a2KczPFj3Q34OgM/8+290Z9joZ0p
wkKNwY03qEO6vlr9E/qA0Y9A6xZBD6QNUmD7jR4Etqq7jtBFgocdjZ6bgMqGQ8Uh
Ss5qapqokrKQrbKZLBHKRCqYGoKwgD1ciXiV6iXuJj+GXDmwte7MZAfFyg5OJngh
GKNCMdU38AYRGrfTWoVH5RC67JlfZMenQBK9sB/XnrB3kOkRbBR/spRYsZg+mbaR
Q7uyPL0hTHyDu1KAe8BpmxYoDrvkmkLPr58CAwEAAaOCBVgwggVUMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBSLsv8vDlH1xvXIpmJ3
htLYjcrMszCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
LmFtYXpvbmF3cy5jb22CKCouczMtYWNjZXNzcG9pbnQudXMtZWFzdC0xLmFtYXpv
bmF3cy5jb22CJCouczMtY29udHJvbC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbYIk
czMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgicqLnMzLWRlcHJl
Y2F0ZWQudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLHMzLWNvbnRyb2wuZHVhbHN0
YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgh0qLnMzLWV4dGVybmFsLTIuYW1h
em9uYXdzLmNvbYIaczMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CMiouczMtYWNj
ZXNzcG9pbnQuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tghwqLnMz
LnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgh0qLnMzLWV4dGVybmFsLTEuYW1hem9u
YXdzLmNvbYImKi5zMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22C
G3MzLWV4dGVybmFsLTIuYW1hem9uYXdzLmNvbYIiczMtY29udHJvbC51cy1lYXN0
LTEuYW1hem9uYXdzLmNvbYIbczMtZXh0ZXJuYWwtMS5hbWF6b25hd3MuY29tgiVz
My1kZXByZWNhdGVkLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgi4qLnMzLWNvbnRy
b2wuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tMBMGA1UdIAQMMAow
CAYGZ4EMAQIBMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
KwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5yMm0wMS5hbWF6
b250cnVzdC5jb20vcjJtMDEuY3JsMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw
AYYhaHR0cDovL29jc3AucjJtMDEuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC
hipodHRwOi8vY3J0LnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5jZXIwDAYD
VR0TAQH/BAIwADCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHcATnWjJ1yaEMM4
W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGNiq0a7AAABAMASDBGAiEAudzKuZ93
XwCkNvsOtCfkpgKu8egAFdXeCG6CPI+muiQCIQDGHiAYvh59sW14WsNF1gX6Wu1A
7JOtTemHgdTsFwmIdAB1AD8XS0/XIkdYlB1lHIS+DRLtkDd/H4Vq68G/KIXs+GRu
AAABjYqtGuwAAAQDAEYwRAIgGECWncBSVe5FGWQ5qgOotqodK6f2dTLwCjQqy3zp
QuACIHPLNnOXzyO8cxbe9iEy1ZWqdh2bqWqMtHUEx4kIY7awAHYAVYHUwhaQNgFK
6gubVzxT8MDkOHhwJQgXL6OqHQcT0wwAAAGNiq0begAABAMARzBFAiBi1XBFN0j+
SJ5PBCByXcJ8xP5anjWJRyuMdK6EkiDzZgIhAKaUpLPdOdiUxx9Xlar4tPz7Bnyw
bx0UFNyiSzPjD6i+MA0GCSqGSIb3DQEBCwUAA4IBAQCtvdXGbz9xJEg9DAPIlfRH
KE2pta2NMLObOqydPjkUFL9dOdgwAxHib9x6X3oTb5PDGqR7DZ5zyf8kdY/UN+nH
3h3WifDXrE2NlVBJ1NwABJ2ZFg2A0G9uchLc0wAvsl86ziQETHWqff7wlGrN5bek
HItY6nc90BH+Jk9nbTa66DMLw26V443hKLcGdq8Fu/N8VING5cw/yMg9HN0tKaZy
o4z9hbT4W12zwCyPPBLxoboTzJY0yTPUYdDbW1b1QIssj/BKwgm0Tfkm6V/MMnqs
BluqB+8VNGPJNhO0zoAI9TMIf2s0MElDyR08ABjvUjy00Gn/g0ZHXSWPEP+NQLoM
VR0TAQH/BAIwADCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHYA2AlVO5RPev/I
FhlvlE+Fq7D4/F6HVSYPFdEucrtFSxQAAAGZY2zFywAABAMARzBFAiEA52TfXblf
xGMn7zs62yXq7rXB/ccKutSfyoReVaLtluACIFL9G5g8WzioAe/Tmx0cJjYXBzof
9go+a5TjVIY4bpnnAHYAwjF+V0UZo0XufzjespBB68fCIVoiv3/Vta12mtkOUs0A
AAGZY2zFywAABAMARzBFAiAdPbpyBei1fmph20ZWi1ZN7nl9b6EDX0s/gYxduL7k
CQIhAMeQp4B56jeit+b3akK3MHyTQoZBgR2CZMBZI6QVk5DUAHUAlE5Dh/rswe+B
8xkkJqgYZQHH0184AgE/cmd9VTcuGdgAAAGZY2zF4AAABAMARjBEAiBpEesssZJD
0SnUOe2Alz/5nGHs/Usxgzgz/xrMmEAXwAIgI90hHJajlzg30MZC3RKkXV8wezmC
pK+h+FLlSvMOUVowDQYJKoZIhvcNAQELBQADggEBAMMItDbq4GvNzuM8t2iBx90Z
F0hcsivxMOHbbxvBRrLtEYjY5wyvmGdWF2t24YFaYzyEMb0qX0YLxLGpoJCf5vIJ
olRHHgdDdkxg354SVQ4+SB1SvpJlAjyzqAGD4XQHAU3t0+jK+9OfJp8Zh57Z3jzI
zhA5ILi5hT3mW3hbHaNfvDpiauB6Sm9T0jc7853Msuh17LvABsIYlt2gVx48ivJc
oLmsInswJM2kWvD8WGTc0sG0wQfT6GNxEGG9anP3odTgdPUNnm8OKqW8nabzmhfu
sMKmxp3ShPpT0KiO5gBlGsMkDKu0+xKB0QjGaRoRbFC/9f0if9jQX5Hiz/xxpS4=
-----END CERTIFICATE-----