Button number changes on each key press

Hallo and congratulations for the great work.
I flashed an esp32 with wizmote-esphome and I tested two remotes.
I have the great problem with both remotes.
MAC address and sequence are recognized and reported correctly. However, each time I press a button another button-number gets recognized.
Example with button 1
[D][esp_now:072]: mac: 6C.<IP_ADDRESS>D.37 (6), data: 80.A<IP_ADDRESS>.B2.5F.00.98.7E.B8 (11)
Event:
{
"event_type": "esphome.wizmote_action",
"data": {
"device_id": "ad01a7a7c8b0bd3d837e938cb62c7a51",
"mac": "6c2990013d37",
"button": "95",
"sequence": "169"
},
"origin": "LOCAL",
"time_fired": "2022-07-16T16:47:38.274838+00:00",
"context": {
"id": "01G83YH492VTSQ8MSQWKYTQDE5",
"parent_id": null,
"user_id": null
}
}
Again button 1
[D][esp_now:072]: mac: 6C.<IP_ADDRESS>D.37 (6), data: 80.AA.<IP_ADDRESS>.58.71.25.CA.01 (11)
Event:
{
"event_type": "esphome.wizmote_action",
"data": {
"device_id": "ad01a7a7c8b0bd3d837e938cb62c7a51",
"mac": "6c2990013d37",
"button": "88",
"sequence": "170"
},
"origin": "LOCAL",
"time_fired": "2022-07-16T16:48:19.735450+00:00",
"context": {
"id": "01G83YJCRQHHSYAKXBN4TJ0QV2",
"parent_id": null,
"user_id": null
}
}
Any help would be highly appreciated.

Hey everyone,
I thought I would comment on this after finding it over two years after my original post that was apparently copied for this code.
https://forum.arduino.cc/t/wizmote/700548
To start with, my code was just preliminary and I was still trying to figure things out.  That being said,  here is some additional info.
Byte 9, I had it labeled as alays 100, this is not the case.  For some reason my initial remote was doing just 100 many times in a row, later I found that it does change between seventy something and around 100.  I have no idea what this byte is actually for.
As far as things changing on each button press for the button byte, I have used 4 different remotes, all were paired previously with bulbs through the app first, I'm not sure if that makes a difference, and all of them send the exact same data for the bytes that don't change and the first byte (0) has always been 129 or 145.  Perhaps this is different for remotes released in different regions?
Also, for the power to stay on while your program is running, pin 16 is connected through a transistor to the voltage regulator's enable pin.  Set pin 16 to HIGH immediately upon startup and then back to LOW to turn the remote off and save power.
As for power, I have also noticed that cheap batteries will cause the microcontroller to have issues and overhear (maybe stuck in a loop with brownout detection?) and the best batteries I have used are the Duracell Optimum.
Now, for the decoding, here's a little code for reference that has worked with every remote I have used.
`
#define REMOTE_TYPE_UNKNOWN 		0
#define REMOTE_NAME_UNKNOWN 		"Unknown"
#define REMOTE_TYPE_CUSTOM			1			// In case you want to identify custom remotes
#define REMOTE_NAME_CUSTOM			"Custom"	// with your own data structure
#define REMOTE_TYPE_PHILLIPS_WIZ	2
#define REMOTE_NAME_PHILLIPS_WIZ	"Phillips WizMote"
unsigned long lastsequence = 0;
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
char mac[18];
char btn[13];
snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0],
mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
unsigned long sequence = 0;
int RType = RemoteType(data, data_len);
if (RType == REMOTE_TYPE_UNKNOWN) {
Serial.println("Unknown Remote Detected - Ignoring Data!");
Serial.printf("Data Length: %d\n", data_len);
for (size_t i = 0; i < data_len; ++i) {
Serial.printf("data[%d] = %d\n", i, data[i]);
}
return;
} else if (RType == REMOTE_TYPE_PHILLIPS_WIZ) {
sequence = (unsigned long) data[4] << 24 | (unsigned long) data[3] << 16
| (unsigned long) data[2] << 8 | (unsigned long) data[1];
strcpy(btn, "BTN:");
strcat(btn, ByteToString(data[6]).c_str());
}
//  If data with same sequence number has been sent more than once, ignore it.
//  This allows remotes to send multiple times to ensure delivery without
//  processing the data more than once.
if (sequence == lastsequence) {
//Serial.println("Duplicate sequence received.");
return;
}
ButtonPressed(mac, btn);
}
lastsequence = sequence;
}
int RemoteType(const uint8_t *data, int data_len) {
if (data_len == 13 && (data[0] == 129 || data[0] == 145) && data[5] == 32 && data[7] == 1) {
// Remote identified as Phillips WizMote
return 2;
//} else if (if statement for custom remote) {
//	return 1
//}
} else {
return 0;
}
}
void ButtonPressed(char *mac, char *btn) {
// Your code to run when a button is pressed
}
`
Hopefully I didn't forget anything there as I copied my existing code and edited (deleted a lot) that wasn't necessary for the example.  And, I hope this helps others to write more programs that can decode the WizMote.  I'm sure there could be improvements to my code as I'm not an expert.  I am open to suggestions.

Hey everyone,
I thought I would comment on this after finding it over two years after my original post that was apparently copied for this code.
https://forum.arduino.cc/t/wizmote/700548
To start with, my code was just preliminary and I was still trying to figure things out.  That being said,  here is some additional info.
Byte 9, I had it labeled as alays 100, this is not the case.  For some reason my initial remote was doing just 100 many times in a row, later I found that it does change between seventy something and around 100.  I have no idea what this byte is actually for.
As far as things changing on each button press for the button byte, I have used 4 different remotes, all were paired previously with bulbs through the app first, I'm not sure if that makes a difference, and all of them send the exact same data for the bytes that don't change and the first byte (0) has always been 129 or 145.  Perhaps this is different for remotes released in different regions?
Also, for the power to stay on while your program is running, pin 16 is connected through a transistor to the voltage regulator's enable pin.  Set pin 16 to HIGH immediately upon startup and then back to LOW to turn the remote off and save power.
As for power, I have also noticed that cheap batteries will cause the microcontroller to have issues and overhear (maybe stuck in a loop with brownout detection?) and the best batteries I have used are the Duracell Optimum.
Now, for the decoding, here's a little code for reference that has worked with every remote I have used.
#define REMOTE_TYPE_UNKNOWN 		0
#define REMOTE_NAME_UNKNOWN 		"Unknown"
#define REMOTE_TYPE_CUSTOM		1		// In case you want to identify custom remotes
#define REMOTE_NAME_CUSTOM		"Custom"	// with your own data structure
#define REMOTE_TYPE_PHILLIPS_WIZ	2
#define REMOTE_NAME_PHILLIPS_WIZ	"Phillips WizMote"
unsigned long lastsequence = 0;

void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
	char mac[18];
	char btn[13];
	snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0],
			mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
	unsigned long sequence = 0;
	int RType = RemoteType(data, data_len);
	if (RType == REMOTE_TYPE_UNKNOWN) {
		Serial.println("Unknown Remote Detected - Ignoring Data!");
		Serial.printf("Data Length: %d\n", data_len);
		for (size_t i = 0; i < data_len; ++i) {
			Serial.printf("data[%d] = %d\n", i, data[i]);
		}
		return;
	} else if (RType == REMOTE_TYPE_PHILLIPS_WIZ) {
		sequence = (unsigned long) data[4] << 24 | (unsigned long) data[3] << 16
				| (unsigned long) data[2] << 8 | (unsigned long) data[1];
		strcpy(btn, ByteToString(data[6]).c_str());
	}
	//  If data with same sequence number has been sent more than once, ignore it.
	//  This allows remotes to send multiple times to ensure delivery without
	//  processing the data more than once.
	if (sequence == lastsequence) {
		Serial.println("Duplicate sequence received.");
		return;
	}
		ButtonPressed(mac, btn);
	}
	lastsequence = sequence;
}

int RemoteType(const uint8_t *data, int data_len) {
	if (data_len == 13 && (data[0] == 129 || data[0] == 145) && data[5] == 32 && data[7] == 1) {
		// Remote identified as Phillips WizMote
		return 2;
	//} else if (if statement for custom remote) {
	//	return 1
	//}
	} else {
		return 0;
	}
}

void ButtonPressed(char *mac, char *btn) {
	// Your code to run when a button is pressed
}

Keep in mind this was written for arduino and for my specific needs in my program.  Re-write as necessary for your own purposes.
Hopefully I didn't forget anything there as I copied my existing code and edited (deleted a lot) that wasn't necessary for the example.  And, I hope this helps others to write more programs that can decode the WizMote.  I'm sure there could be improvements to my code as I'm not an expert.  I am open to suggestions.

Hi @kb1sph,
Thanks for your input on this!

Also, for the power to stay on while your program is running, pin 16 is connected through a transistor to the voltage regulator's enable pin. Set pin 16 to HIGH immediately upon startup and then back to LOW to turn the remote off and save power.

This information is pure gold for me :slightly_smiling_face: I wondered why my custom program was only running during a button press. This will also enable me to implement the detection of long button presses.

As for power, I have also noticed that cheap batteries will cause the microcontroller to have issues and overhear (maybe stuck in a loop with brownout detection?) and the best batteries I have used are the Duracell Optimum.

I also encountered the same problem, thinking that my code ran into a loop because the remote's LED stayed on although I released the button. After some time I changed the batteries and everything was fine again. Using my custom firmware I only send the sequence number ( 4 bytes stored inside EEPROM ) as well as the button number ( 1 byte ) read from the PCA6416A chip (https://www.nxp.com/docs/en/data-sheet/PCA6416A.pdf) conntected via I²S. Using your input I can now try to add an additional byte for long button presses (true/false).
One thing I also noticed using wireshark in monitor mode is, that the remote sends out 12 packets on each wifi channel. I implemented my code so that it only sends one packet on one channel hoping that this will increase battery life.
Once I clean up my code, I will push it and post a link to the repository here for anyone interested in this.

Hi,
I uploaded my firmware source code. You can find it at : https://github.com/krakowski/wizmod
If anyone is interested in improvements, please feel free to open a PR.

One thing I also noticed using wireshark in monitor mode is, that the remote sends out 12 packets on each wifi channel. I implemented my code so that it only sends one packet on one channel hoping that this will increase battery life.

Interesting.  I have not played with wireshark with wireless.  Perhaps this is a feature of the newer remotes?  In my testing, with one of the first remotes that came out, I had to have the receiving chip on channel 1, no other channels would work.  I was not able to connect to my router as well as receive ESP-Now signals on the same channel as the router, which is supposed to be possible as long as you are set to WIFI_MODE_APSTA, because the remote was only sending on channel 1.  I'll have to check one of my newer remotes.
I'll have to look into how to use wireshark with wireless.  Any pointers on this?

Also, yours has a PCA6416A??? Mine had a 74HC165A, which meant they had to put the sleep button on a gpio off of the ESP chip.  It seems there are multiple versions even though they look pretty much the same.  I am now wondering about my newer remote.  I have 3 older remotes and one newer one.  The older remotes had kind of a glossy finish to the shell while the newer one has a matte finish.  Which one do you have?
Here is a copy of a crude, basic program I wrote for the WizMote which also allowed holding multiple buttons, including the sleep button which is not on the 74HC165A if anyone has the older remotes.
/*  NOTES FOR FLASHING!!!!!!!!
 *
 *   WizMote uses an ESP8266 (ESP-WROOM-02D) with only 2MB of flash.
 *   Setting the flash size higher will cause the sequence to not be written to EEPROM.
 *   (This was the original first generation remotes, it appears things may have changed, so I can't guarantee this)
*/

#include <ESP8266WiFi.h>
#include <espnow.h>
#include <EEPROM.h>

// Added this and the associated code below, which I ran on the first write, to clear whatever was store in
// the eeprom from the factory as I did not attempt to read and decode what the factory programming stores where.
#define RESET_EEPROM false

int shift = 13;                                                           // Define Connections to 74HC165
int dataIn = 5;
int clockIn = 4;

byte buttonshift;
int buttonsleep;

unsigned long loopstart = 0;
unsigned long loopdelay = 25;                                            // Delay in between repeating signal
int buttonrepeat = 10;                                                     // Number of times to repeat signal
int randomnumber;

uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};        // Broadcast to all devices

typedef struct wizstructure {                                             // Data to send by ESP-Now
  byte program;                                                           // Seems to always be set to 145 when power button is pressed and 129
                                                                          // for any other button which suggests it might be used in the programming
                                                                          // sequence for bulbs which make you press the power button
  byte seq[4];                                                            // Incremental number sent each time a button is pressed. This is done in
                                                                          // order to prevent cloning the signal and and making sure each button press
                                                                          // is uniquely identified. It obviously does not defeat reverse engineering. :)
  byte byte6 = 32;                                                        // Unknown, but this seems to always have a value of 32
  byte button = 0;                                                        // Identifies which button is being pressed
  byte byte8 = 1;                                                         // Unknown, but this seems to always have a value of 1
  byte byte9 = 100;                                                       // Unkown. Initial testing on my oldest remote had this as always 100,
  byte byte10;                                                               // on newer remotes it can vary.
  byte byte11;
  byte byte12;
  byte byte13;
} wizstructure;
wizstructure Wiz;

void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {                  // Callback function after data is sent
  Serial.print("Last Packet Send Status: ");
  if (sendStatus == 0) {
    EEPROM.commit();
    Serial.println("Delivery success");
  }
  else {
    Serial.println("Delivery fail");
  }
}

uint8_t shiftIn165(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { // Custom shiftIn because the standard arduino function has the LOW and HIGH backwards for 74HC165A
  uint8_t value = 0;
  uint8_t i;

  for (i = 0; i < 8; ++i) {
    digitalWrite(clockPin, LOW);
    if (bitOrder == LSBFIRST) {
      value |= digitalRead(dataPin) << i;
    }
    else {
      value |= digitalRead(dataPin) << (7 - i);
    }
    digitalWrite(clockPin, HIGH);
  }
  return value;
}

void readbuttons() {
  digitalWrite(shift, LOW);                                               // Write pulses to shift Data
  delayMicroseconds(5);
  digitalWrite(shift, HIGH);
  delayMicroseconds(5);
  buttonshift = ~shiftIn165(dataIn, clockIn, LSBFIRST);                   // Read shift register inputs and flip bits to make it easier to understand
  buttonsleep = ~(digitalRead(14) >> 0) & 1;                              // Read sleep button state

  Wiz.program = 129;                                                      // Default value if On button is not being pressed
  switch (buttonshift) {                                                // Check for other buttons pressed and store the value in the Wiz structure
    case 64:                // 01000000
      Wiz.button = 1;       // On
      Wiz.program = 145;    // Program?
      break;
    case 128:               // 10000000
      Wiz.button = 2;       // Off
      break;
    case 16:                // 00010000
      Wiz.button = 16;      // 1
      break;
    case 32:                // 00100000
      Wiz.button = 17;      // 2
      break;
    case 4:                 // 00000100
      Wiz.button = 18;      // 3
      break;
    case 8:                 // 00001000
      Wiz.button = 19;      // 4
      break;
    case 1:                 // 00000001
      Wiz.button = 8;       // Dim
      break;
    case 2:                 // 00000010
      Wiz.button = 9;       // Bright
      break;
    case 0:                 // None of the previous detected, most likely sleep is pressed as it is on a separate input on the MCU.
      Wiz.button = 0;
      break;
    default:
      if (buttonshift > 128) {
        Wiz.button = 2;
      } else {
        Wiz.button = buttonshift + 128;
      }
  }
  if (buttonsleep && Wiz.button == 0) {                                                      // Determine if sleep is pressed before anything else as it is on GPIO 14 and not the shift register
    Wiz.button = Wiz.button + 3;
  } else if (buttonsleep && Wiz.button > 0) {
    Wiz.button = Wiz.button + 13;
  }
}

void setup() {
  digitalWrite(16, HIGH);                                                 // Pin state needed to keep voltage regulator on
  pinMode(16, OUTPUT);                                                    // Turn on output to voltage regulator to keep it in while the program is running
  pinMode(14, INPUT);                                                     // Sleep button input (because there are 9 buttons and 8 inputs on shift register)
  pinMode(shift, OUTPUT);                                                 // Shift pin for 74HC165A
  pinMode(clockIn, OUTPUT);                                               // Clock Pin for 74HC165A
  pinMode(dataIn, INPUT);                                                 // Data Pin for 74HC165A

  readbuttons();                                                          // Read buttons on setup to get a quick reading before the rest of setup.
                                                                                // This helps get the button pressed right away so that it is not lost if you
                                                                                // let go of the button while it is still going through the setup.

  Serial.begin(74880);
  EEPROM.begin(512);

  if ( RESET_EEPROM ) {
    for (int i = 0; i < 512; i++) {
      EEPROM.write(i, 0);
    }
    EEPROM.commit();
    delay(500);
  }

  WiFi.mode(WIFI_STA);                                                    // Initialize ESP-Now
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);                         // Set ESP-Now mode
  esp_now_register_send_cb(OnDataSent);                                   // Set callback function for data sent

  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);     // Register slaves/peers
}

void loop() {
  digitalWrite(16, HIGH);                                                 // I duplicated this in the loop in case you were holding the
                                                                                // bright or dim buttons as the end of the loop shuts it off.
  randomSeed(analogRead(0));
  unsigned long sequence = (unsigned long)EEPROM.read(0) << 24
                           | (unsigned long)EEPROM.read(1) << 16
                           | (unsigned long)EEPROM.read(2) << 8
                           | (unsigned long)EEPROM.read(3);
  Serial.print("EEPROM Sequence: ");
  Serial.println(sequence);
  if (sequence ==<PHONE_NUMBER>) {
    sequence = 1;
  }
  else {
    sequence++;
  }
  EEPROM.write(0, (sequence >> 24));
  EEPROM.write(1, (sequence >> 16));
  EEPROM.write(2, (sequence >> 8));
  EEPROM.write(3, (sequence));
  Wiz.seq[3] = (sequence >> 24);
  Wiz.seq[2] = (sequence >> 16);
  Wiz.seq[1] = (sequence >> 8);
  Wiz.seq[0] = (sequence);
  Wiz.byte10 = random(255);    // This was for testing because these bytes seemed random
  Wiz.byte11 = random(255);
  Wiz.byte12 = random(255);
  Wiz.byte13 = random(255);

  uint8_t i;
  for (i = 0; i < buttonrepeat; ++i) {
    esp_now_send(broadcastAddress, (uint8_t *) &Wiz, sizeof(Wiz));        // Send data to slaves
    delay(loopdelay);
  }
  readbuttons();
  digitalWrite(16, LOW);                                                  // Turn off voltage regulator to save battery power
  if (Wiz.button < 8 || Wiz.button > 9) {                                 // If holding + or - the loop will continue until released and then power off
    while (1);                                                            // If other buttons are being held, stop loop and power off once released
  }
}

Keep in mind, I am far from an expert coder and just like to play around with things.  I'm sure there are some things in this that I just wasn't understanding, some things that could be improved, or even things that have changed over time with the remotes changing.

Hi,
I uploaded my firmware source code. You can find it at : https://github.com/krakowski/wizmod
If anyone is interested in improvements, please feel free to open a PR.

Just looking at your code for a moment... Am I correct in that you only read port 0 inputs?  If so, there are 8 inputs, but 9 buttons, are there not?  Of course, I could be missing something because I am tired and on meds for some neck pain right now.  LOL

Hi,
regarding Wireshark, I just followed this documentation: https://wiki.wireshark.org/CaptureSetup/WLAN#linux
airmon-ng is pretty simple to use (requires root rights). After setting up wlan0 in monitor mode, you simply choose the mon0 interface inside Wireshark.
My remote has a matte finish and uses I2C. Also, the version printed on the PCB is V1.3, so there really seem to be different versions.
Yes, you are right, I only read port 0. Pressing the sleep button (you mean the button with the moon printed on it, right?) results in all bits set to 0, so I thought this was how they implemented this particular button. But you might be right. The button most likely is connected to one of the pins of port 1. I didn't use this button, so I didn't really bother me. Hope your neck pain gets better 😄

Yes, I meant the moon button.  It is meant as a sleep mode for the lights, it dims them lower than you can with the normal dim button.  You can also set it for circadian rythm and it will slowly dim at night and brighter from a soft white to bright white in the morning.
Hmmm, I haven't opened my older remote up recently to see if there's a version number printed on it, but I would assume they either didn't print one or that it's going to be the 1.0 version.
Let me know if you read port 1 and get a result for the extra button vs it being connected to a gpio pin like the older ones.  I think I'm going to have to open mine up and see what the internal differences are now.
Did the pin 16 still work on your newer remote to keep it on?

Ok, so, I opened up my newest remote, which has more of a matte finish, but the exact same labeling as the older ones.  The board in side is the exact same thing.  It appears that maybe they switched the case first, then updated the circuit board later?  Where did you get your remote from?  Mine have all been from Home Depot.  Perhaps they have older stock still.

When I get a moment, I'll have to take a picture of the button side.  I didn't think to do that because I was just showing the chip differences.  It might have a date.  It's not very legible in the picture, but mine just has some seemingly random numbers with V00 at the end on the chip side.  None of it appears to be in the same format as your date.  I'm thinking yours is probably the newer design and the Home Depot here probably has a back stock in their warehouses of the older ones.  Home Depot was one of the first companies in the US to carry the Phillips Wiz line of products.
It appears that you have a different regulator as well.  Yours is 8 pin while mine is 6 pin.

Does anyone have a firmware image from a device with this issue?

I worked out the encryption and authentication schemes used for the WizMotes, both new and old. I could turn this into a PR if there is interest. I'd like to get some input on a few points first.
Inevitably, key material is needed in order to encrypt/decrypt or sign/verify. There's a couple of ways about this.
The key is stored on the WizMote and anything it is paired with. For now, it can be obtained by using esptool and a USB to serial adapter to read the flash memory off the device. The WizMotes I have seen are very easy to open and there's already clearly labeled programming pins on the board. Pros: offline, no legal complications. Cons: requires some technical skill and equipment, opens device, they may encrypt the flash in the future, need to manually input the key.
For some devices, like @drbiosignals newer WizMote, the key is generated deterministically. However, doing this requires a salt, which is not easily obtainable, and may not be distributable. Pros: offline, no setup or intervention needed by the user. Cons: potential legal complications, does not work on older WizMotes.
There may be a third option, but it probably is not a realistic one due to legal complications. As far as the theory goes, we could emulate adding a new Wiz light bulb, tricking another light bulb (or even the cloud) into handing out the keys. The process would require reimplementing more Wiz IP than anything else here, including an SSL certificate. Pros: no user intervention, works on all devices. Cons: legal, requires access to cloud or at least one real Wiz light.
So the first option is the least legally hazardous, works on all devices, but is kind of a pain. If I went with this, the next question is, what's the best way to hand the key off to wizmote-esphome? Build time option? Uploaded at runtime?
And finally, is there a use case for authentication? It makes sense to solve the encryption as it's not useful at all if it can't be deciphered. However I am not sure how practically concerned we are that it is authenticated. It is trivial to bypass, and transmission errors would be caught by mechanisms on lower levels.
Thanks for your thoughts.

@kueblc I've the blue PCB with the same issue. I will send you my firmware. It would be nice if you could share your knowledge about the authentication / encryption or make a PR and how to obtain the key from the image.
Thanks a lot.

Did the pin 16 still work on your newer remote to keep it on?

My remote setting pin 16 HIGH does not keep it on.
Holding a button keeps it on and allows my program to execute; letting go of the button the LED goes dark a moment later and according to serial output my program stops too.
I've tried setting pins 0 to 20 to HIGH in case this worked, and then I could bisect to find the pin, but the power still drops. Maybe before all the pins are set, seems unlikely as I'd expect them to loop pretty fast, but serial output is confused since maybe setting random pins high interferes with TX... I'll do them one at a time in a series of tests...
16 seems to normally be a WAKE pin for esp8266, so I'm surprised my remote doesn't stay on.
This is the remote:

I got another remote. Which by eye looks the same components and layout. But the colour and markings are different. The esp tin is older.
On this one, pin 16 DOES control the power, which is great news.

My remote setting pin 16 HIGH does not keep it on (I also tried LOW, just in case...)

The buttons are connected to a 3-pin dual diode. Looks like it's a transistor, but it's not.  With two inputs, one on each is connected to each button and the others are all connected together.  You should see a trace connection then.  The single output goes to the voltage regulator enable pin. You'll need to do a continuity test from the pins that are connected together to the pins on the microcontroller to see which one they are connected to.  And, depending on the voltage regulator used if your model is different, it could be low for enable instead of high.


Passing props and style to native components

All native components should be wrapped in normal components and they should coordinate setting props.
The current style solution is a hack.

Done as of #6


WIP: Fix Out of Memory failure in test TensorTest.Tensor64BitDimension

@caffe2bot test this please

@caffe2bot add to whitelist

@mingzhe09088 We should only wrap the line(s) that throw the OOM exception in the test.

I am not sure why the conda build is still failing, but it looks like this error was fixed on it. I would still check this in despite the conda failure

@bddppq From the previous testing result, when the OOM error happened, all the following lines in that function also failed. So I protect the following lines.

@mingzhe09088 In case OOM error happened the rest of the test should be skipped (just early return).

@bddppq Thanks! I've pushed a fix.


Add LaTeX template for Sci-tech manuscript

Use template found in sealion-mission-architecture:

https://github.com/ODU-CGA-CubeSat/sealion-mission-architecture/blob/main/templates/manuscript.tex.jinja2
https://github.com/ODU-CGA-CubeSat/sealion-mission-architecture/tree/main/manuscript

standalone template available at https://github.com/ODU-CGA-CubeSat/manuscript-templates with example usage in https://github.com/ODU-CGA-CubeSat/manuscript-example


SW-4891 Single Deliverable redux and mock data

Implement redux for single deliverable
Add method to DeliverableService that returns mock data for now
Only 1 mock document added for now

Wired it up in a random view to verify the dispatch / select work as expected:

Merge activity

Feb 22, 4:12 PM EST: @nickgraz started a stack merge that includes this pull request via Graphite.

I merged the first one before I read your comment, sorry about that. I have another open PR that refactors to use async thunks for both deliverables search and deliverable fetch


Draft: feat: query support for geo within and intersects + dynamic GraphQL operator types

Description
Old PR: #3001

[X] I have read and understand the CONTRIBUTING.md document in this repository.

Type of change

[ ] Chore (non-breaking change which does not add functionality)
[ ] Bug fix (non-breaking change which fixes an issue)
[X] New feature (non-breaking change which adds functionality)
[ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
[ ] Change to the templates directory (does not affect core functionality)
[ ] Change to the examples directory (does not affect core functionality)
[ ] This change requires a documentation update

Checklist:

[ ] I have added tests that prove my fix is effective or that my feature works
[ ] Existing test suite passes locally with my changes
[ ] I have made corresponding changes to the documentation

@AlessioGr what makes this a draft and what is missing still to be merged?

@AlessioGr what makes this a draft and what is missing still to be merged?

@DanRibbens I'm currently working on adding tests for the within and intersects operators. After that, I think this can be merged!

In the filter options of the list view I was expecting to see intersects and within as operator options:

This should be added before this PR is merged.

In the filter options of the list view I was expecting to see intersects and within as operator options:
This should be added before this PR is merged.

@DanRibbens The issue here is that even the near field doesn't actually work in the admin panel filter options anyways - so I didn't even bother for within and intersects.
Given that the issue has existed before this PR, I think it's out of scope. What do you think?

@DanRibbens I did some more digging. This would be a simple rest API call:
{
  "$and": [
    {
      "point": {
        "$near": {
          "$geometry": {
            "type": "Point",
            "coordinates": [
              1,
              -7
            ]
          },
          "$maxDistance": 1000
        }
      }
    }
  ]
}

and it works perfectly. However, the WhereBuilder in the admin panel requires queries to be in this special and > or > and format, which makes the query look like this:
{
  "$and": [
    {
      "$or": [
        {
          "$and": [
            {
              "point": {
                "$near": {
                  "$geometry": {
                    "type": "Point",
                    "coordinates": [1, -7]
                  },
                  "$maxDistance": 1000
                }
              }
            }
          ]
        }
      ]
    }
  ]
}

This causes the following error:
$geoNear, $near, and $nearSphere are not allowed in this context
Not sure what the issue is - looks like it could be a limitation in MongoDB.

@DanRibbens I've fixed the issue with the WhereBuilder!
The issue was that the huge and[][0][or][0][and][0] Where queries the WhereBuilder component generates did NOT properly get flattened by flattenWhereConstrains before. Now they do, and it works beautifully.
Given that it works now, I've added back within and intersects to the WhereBuilder. It also filters and works perfectly:

The issue here is that the where query here is represented as an [object Object] in the text field.
This would be the alternative:
https://github.com/payloadcms/payload/assets/70709113/5b512380-5051-452e-81cf-90169fd5f232
can't say I prefer this.
I think this would be best addressed in a separate PR, as it needs some design work as well. Where queries as complex as this one cannot be represented in a one-line text field. Leaving it as [object Object] feels like the nicest option to me.

@DanRibbens I've adressed them!


Feature: allow specifying export directory format

The export command already provides the option --export-by-date to export photos to directories based on the photo's date created, e.g. DEST/2019/12/20/photoname.jpg.
I would like to request this directory format be customisable to allow for formats like DEST/2019/2019-12-20/photoname.jpg. Ideally, the formatter would allow for locations (city, country?) as well, to allow for exporting straight into e.g. DEST/2019/2019-12-20 Tokyo/photoname.jpg.

@AaronVanGeffen I like this idea and I've been thinking about how to allow some sort of templating system for exporting not only directory names but also the image name.   As for location, osxphotos does not currently provide access to the location name.  I see your script does get location data for older databases but Photos 5 stores location data in binary blobs and I haven't had time to reverse engineer this:
https://github.com/AaronVanGeffen/ExportPhotosLibrary/blob/0fa41d75ea115614792cc0526acf1646c9df69dd/export_photos.py#L149-L169

Thinking about this... I already use mako templating system for writing the XMP sidecars.  It would be possible to use this to allow the user to specify filename or directory using something like:
osxphotos export ~/Desktop/export --filename="${photo.original_filename}_${photo.date}" --directory="${photo.date.year}/${photo.date.date().isoformat()}"
Demo code showing this would work (p is a single PhotoInfo object):
>>> template = "${photo.original_filename}_${photo.date}"
>>> from mako.template import Template
>>> template = "${photo.original_filename}_${photo.date}"
>>> mytemplate = Template(template)
>>> mytemplate.render(photo=p)
'IMG_7922.JPG_2011-07-16 21:37:58-07:00'
>>> template = "${photo.date.year}/${photo.date.date().isoformat()}"
>>> mytemplate = Template(template)
>>> mytemplate.render(photo=p)
'2019/2019-07-19'

This implementation would be very powerful and give the user full control over the naming of exported images.  The downside of this implementation is that it also allows the user to enter arbitrary python code that would be executed by osxphotos.  Probably not a big deal as the user already has full access to the terminal but it still provides a vector to inject code, for example, if the user relied on a shell script to run osxphotos and didn't realize what they were feeding in.
This would also require the user to have a basic understanding of simple python syntax.  An alternative would be to roll my own templating system that does simple substitutions e.g. --filename="{original_name}_{yyyy}_{mm}" and substitute for values in the {} but that doesn't sound fun and would definitely be less flexible than a full templating system.

I’m working on an implementation using a simple roll-my-own template system.  I experimented with both and decided that using a full template engine like Mako was overkill and would be overly complicated for users who weren’t programmers but just wanted to use the CLI.  Current thoughts on implementation are something like this:
--directory = “{yyyy}{yy}-{mm}-{did}”
--filename = “{original_name}{yyyy}”
Would produce something like:
Directory = 2020_20-03-13
Filename = photoname_2020.jpg
Will include other options like {month} for full month name in locale appropriate name, etc.

That sounds like it would certainly suffice for most purposes. I agree such formatting codes would be less intimidating, too. Having some description in addition to dates would be nice, but probably best left for a future extension.

@AaronVanGeffen I’m planning on providing access to photo title, description, as well.  I’m also torching with the idea of allowing multi-valued attributes like keywords and albums to allow a photo to be exported to multiple locations or with multiple names (but use hard links to avoid duplicate files).  E.g. you could do something like this to export to albums:
--directory “{album}” and if photo was in albums “Vacation 2019” and “Ski Trip” it would result in:
Vacation 2019/photoname.jpg
Ski Trip/photoname.jpg
I’ll play with this but will defer implementation to future version.  Let me know if you have thoughts on this or would find it useful.

Sounds like a good feature; I'm sure some would appreciate that. However, personally, I don't make a lot of use of albums. Instead, I'd really like to use the dominant location or 'moment name' for exported folders.

@AaronVanGeffen initial version of this feature is implemented in 0.23.3.  command line export command has a new option --directory that allows you to specify the output directory name based on a templating system: e.g.
osxphotos export ~/Pictures/export --directory "{created.year}/{place.name}"
See osxphotos help export for full details on the templating system. I've not yet extended this to the output filename but plan to do so in the future.

I've re-written the very basic MVP template engine that is in 0.23.3 to allow per-item substitution in case of None value. E.g. if item doesn't have reverse geolocation data, you could do this:
--directory "{created.year}/{place.name,NoLocation}"
Anything after the , gets used if the value is None.  This can be specified for each template replacement value.
Still working on the code so it's not on github yet.  I am thinking about adding a PhotoInfo.render_template() method so the rendering can be done directly by the PhotoInfo object.

Interesting. In the case of {place.name}, what level of geographical detail would be used? Country, state, city, street? Would this be finetunable?

Yes, currently, the following are available:

Substitution
Description

{name}
Filename of the photo

{original_name}
Photo's original filename when imported to Photos

{title}
Title of the photo

{descr}
Description of the photo

{created.date}
Photo's creation date in ISO format, e.g. '2020-03-22'

{created.year}
4-digit year of file creation time

{created.yy}
2-digit year of file creation time

{created.mm}
2-digit month of the file creation time (zero padded)

{created.month}
Month name in user's locale of the file creation time

{created.mon}
Month abbreviation in the user's locale of the file creation time

{created.doy}
3-digit day of year (e.g Julian day) of file creation time, starting from 1 (zero padded)

{modified.date}
Photo's modification date in ISO format, e.g. '2020-03-22'

{modified.year}
4-digit year of file modification time

{modified.yy}
2-digit year of file modification time

{modified.mm}
2-digit month of the file modification time (zero padded)

{modified.month}
Month name in user's locale of the file modification time

{modified.mon}
Month abbreviation in the user's locale of the file modification time

{modified.doy}
3-digit day of year (e.g Julian day) of file modification time, starting from 1 (zero padded)

{place.name}
Place name from the photo's reverse geolocation data

{place.names}
list of place names from the photo's reverse geolocation data, joined with '_', for example, '18th St NW_Washington_DC_United States'

{place.address}
Postal address from the photo's reverse geolocation data, e.g. '2007 18th St NW, Washington, DC 20009, United States'

{place.street}
Street part of the postal address, e.g. '2007 18th St NW'

{place.city}
City part of the postal address, e.g. 'Washington'

{place.state}
State part of the postal address, e.g. 'DC'

{place.postal_code}
Postal code part of the postal address, e.g. '20009'

{place.country}
Country name of the postal code, e.g. 'United States'

{place.country_code}
ISO country code of the postal address, e.g. 'US'

That looks very detailed! Great work. I take this to mean {place.name} from the example is basically the string Photos.app uses, then?

The only place information not directly available in current implementation is the list of names (which are sorted by area) because there are sometimes duplicates and often a different number of these depending on location.    Here's examples of the place.names from my photos:

['Japanese American National Museum', 'Japanese American National Museum', 'Little Tokyo', 'Los Angeles', 'Downtown', 'Los Angeles', 'Los Angeles', 'Los Angeles', 'California', 'United States']
['Adventure City', 'Adventure City', 'Stanton', 'Anaheim', 'West Anaheim', 'Anaheim', 'Orange', 'California', 'United States']
['White Point Nature Preserve & Education Center', 'White Point Nature Preserve & Education Center', 'San Pedro', 'San Pedro', 'San Pedro', 'Los Angeles', 'Los Angeles', 'California', 'United States']
['Santa Catalina Island', 'Santa Catalina Island', 'Santa Catalina Island', 'Los Angeles', 'California', 'United States']

If you use place.names in the template, it joins all together.  It would take some additional work to give you access to individual elements of the place list in the template.

That looks very detailed! Great work. I take this to mean {place.name} from the example is basically the string Photos.app uses, then?

No, it's the most detailed (local) name in the names list.  E.g. in the names list:

['Japanese American National Museum', 'Japanese American National Museum', 'Little Tokyo', 'Los Angeles', 'Downtown', 'Los Angeles', 'Los Angeles', 'Los Angeles', 'California', 'United States']

place.name would be 'Japanese American National Museum'.  In Photos, the map info shows 'Japanese American National Museum, Los Angeles, California, United States' which is a subset. I've not figured out what algorithm Photos uses to build the string it displays.

I see, that makes sense. Thank you for the clarification!

Note to self: This might be helpful in decoding the various place names in Photos:
https://developer.apple.com/documentation/corelocation/clplacemark

Making progress.  I think I've reverse-engineered how Photos constructs the reverse geolocation name it displays in the info dialog so I should be able to provide that (perhaps by changing place.name to return this).  I have also mapped each of the place types in place.names to their meaning so I'll be able to provide direct access to the following (which seem to correspond to the attributes of a Core Location CLPlacemark object).  The number is the corresponding placeType value in sortedPlaceInfos

1 country
14 postalCode
2 administrativeArea (The state or province associated with the placemark.)
3 subAdministrativeArea (Additional administrative area information for the placemark.)
4 locality (The city associated with the placemark.)
6 subLocality (Additional city-level information for the placemark.)
17 thoroughfare (The street address associated with the placemark.)
12 subThoroughfare (Additional street-level information for the placemark.)
11 region (The geographic region associated with the placemark) -- seems to be used for island name
9 inlandWater (The name of the inland water body associated with the placemark.)
7 ocean (The name of the ocean associated with the placemark.)
8 areasOfInterest (The relevant areas of interest associated with the placemark.)

For Photos <= 4, the type associated with place name is different and there is less information available.  In my database, I've figured out the following for RKPlace.type:

45: areasOfInterest (The relevant areas of interest associated with the placemark.)
44: body of water (includes both inlandWater and ocean)
43: subLocality (Additional city-level information for the placemark.
16: locality (The city associated with the placemark.)
4: subAdministrativeArea (Additional administrative area information for the placemark.)
2: administrativeArea (The state or province associated with the placemark.)
1: country

The name displayed in Photos is a maximum of three of these, in the following order:

If areasOfInterest defined: 45, 16, 1
Else if locality defined: 16, 2, 1
Else if administrativeArea defined: 2, 1

@AaronVanGeffen I've updated the template system in v0.24.1 to provide access to the detailed place name information. The following fields are all available to specify in the --directory option for osxphotos export.  Note, some of these changed from what I previously posted here.  You can also now specify a default value in case the substitution value is None.  For example,
osxphotos export ~/Desktop/export --directory "{created.year}/{place.name.city,NO_CITY}"

Substitution
Description

{name}
Filename of the photo

{original_name}
Photo's original filename when imported to Photos

{title}
Title of the photo

{descr}
Description of the photo

{created.date}
Photo's creation date in ISO format, e.g. '2020-03-22'

{created.year}
4-digit year of file creation time

{created.yy}
2-digit year of file creation time

{created.mm}
2-digit month of the file creation time (zero padded)

{created.month}
Month name in user's locale of the file creation time

{created.mon}
Month abbreviation in the user's locale of the file creation time

{created.doy}
3-digit day of year (e.g Julian day) of file creation time, starting from 1 (zero padded)

{modified.date}
Photo's modification date in ISO format, e.g. '2020-03-22'

{modified.year}
4-digit year of file modification time

{modified.yy}
2-digit year of file modification time

{modified.mm}
2-digit month of the file modification time (zero padded)

{modified.month}
Month name in user's locale of the file modification time

{modified.mon}
Month abbreviation in the user's locale of the file modification time

{modified.doy}
3-digit day of year (e.g Julian day) of file modification time, starting from 1 (zero padded)

{place.name}
Place name from the photo's reverse geolocation data, as displayed in Photos

{place.name.country}
Country name from the photo's reverse geolocation data

{place.name.state_province}
State or province name from the photo's reverse geolocation data

{place.name.city}
City or locality name from the photo's reverse geolocation data

{place.name.area_of_interest}
Area of interest name (e.g. landmark or public place) from the photo's reverse geolocation data

{place.address}
Postal address from the photo's reverse geolocation data, e.g. '2007 18th St NW, Washington, DC 20009, United States'

{place.address.street}
Street part of the postal address, e.g. '2007 18th St NW'

{place.address.city}
City part of the postal address, e.g. 'Washington'

{place.address.state_province}
State/province part of the postal address, e.g. 'DC'

{place.address.postal_code}
Postal code part of the postal address, e.g. '20009'

{place.address.country}
Country name of the postal address, e.g. 'United States'

{place.address.country_code}
ISO country code of the postal address, e.g. 'US'

I've update the template system to allow multi-valued template substitutions so the following now work as substitutions for --directory: {album}, {keyword}, {person}.  This means you can export by album using the following:
osxphotos export /path/to/export/folder --directory "{album}"
Note: This could result in duplicate copies of photos being exported if a photo belongs to more than one album.
You can specify a default value for photos not in an album thusly:
osxphotos export /path/to/export/folder --directory "{album,DEFAULT_ALBUM_NAME}"


Update CONTRIBUTING.md

Fixes #144
Add the instruction of using Git LFS in CONTRIBUTING.md to download the datasets, in order to pass two tests related to the dataset inputs_data_24.25.nc.

Codecov Report
All modified and coverable lines are covered by tests :white_check_mark:

Comparison is base (dbdff0f) 94.09% compared to head (7e35a3b) 94.09%.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop     #146   +/-   ##
========================================
  Coverage    94.09%   94.09%
========================================
  Files           21       21
  Lines         1134     1134
========================================
  Hits          1067     1067
  Misses          67       67

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

There is now a formatting error flagged by the linting which needs to be resolved:

Now it has trailing whitespace (don't worry, happens to me all the time!):

This shouldn't happen if pre-commit is installed? @TZTsai - have you got pre-commit set up on your machine? If you have then it shouldn't permit you to push commits that fail the qa action.

This shouldn't happen if pre-commit is installed? @TZTsai - have you got pre-commit set up on your machine? If you have then it shouldn't permit you to push commits that fail the qa action. That's actually described in CONTRIBUTING.md 😄

Ah sorry. I do have pre-commit installed, but I directly edited the file on GitHub.

That explains it 😄


cdk8s import missing k8s 1.19 API spec on<EMAIL_ADDRESS>

Description
Looks like we've run into this issue before here: https://github.com/cdk8s-team/cdk8s-cli/issues/23
I don't really want to downgrade all the way to v1.0.0-beta.27 from v1.0.92 in order to work around this issue. Is there a new recommended workaround for this?
How to reproduce
using<EMAIL_ADDRESS>run the following command in a TypeScript cdk8s app:
cdk8s import<EMAIL_ADDRESS>
Observed behavior:
The following URLs:

https://raw.githubusercontent.com/awslabs/cdk8s/master/kubernetes-schemas/v1.19.8/_definitions.json
https://raw.githubusercontent.com/awslabs/cdk8s/master/kubernetes-schemas/v1.19/_definitions.json

Both respond with a 404.

Expected Behavior
k8s 1.19 is available to download via cdk8s import<EMAIL_ADDRESS>as the cdk8s docs imply here:

Looks like running this works!
cdk8s import<EMAIL_ADDRESS>
This can probably be closed with a little bit better error-logging and clearer docs that spell out that

You can only pick from the versions listed here: https://github.com/cdk8s-team/cdk8s/tree/master/kubernetes-schemas
The version needs to include all three numbers.

Oof - that sounds like it was frustrating to debug. 😕
I agree, we should add some validation here to avoid confusion in the future (and update any docs as needed). Thanks for reporting this.


Missing dependency "malkusch/php-index"

The package "malkusch/php-index" is no longer available on GitHub or Packagist.
Is there a replacement for it?

You may use
https://github.com/bmdevel/bav and/or
https://github.com/bmdevel/php-index.
It is a simple fork. Not really maintained however


Some responsive display changes

Fixed the changing width of the sidebar - made it fixed width so it looks nicely for any screen width.
Also fixed that weird offset problem in the navbar with the location of auth stuff.

No word wrap just the weird edges

I get this error in my console
Refused to apply style from 'http://localhost:3000/antd/dist/antd.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.

I get this error in my console
Refused to apply style from 'http://localhost:3000/antd/dist/antd.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.

@LeshemNoa I am trying to understand if this and the weird things I'm seeing above are related..


Any plans to support Amazon Neptune?

Is there any plans to support Amazon Neptune?

Yes, we're planning on supporting all AWS services.
We're a bit behind on botocore versions, so we don't have Neptune in our list of unimplemented services yet: https://github.com/rusoto/rusoto/issues/436 .

https://github.com/rusoto/rusoto/pull/1101 bumps our version of botocore to the latest release which includes Neptune. A prerequisite for adding the service. 😄

https://github.com/rusoto/rusoto/pull/1124 👍


Syntax sugar & pattern

Hi, we started using the same component pattern used here but we were wonering if there would be a better way to write the props in haml code.

Take this example. Some times they are many component like this and your haml start to be crowded with ruby props hashes all around which kind of defeat the purpose of the view clarity.
You could put them in helpers put thats not very encapsulated. Or presenters but they are not necessarily tied to an object.
Can I ask how you did this in the lonely planet app?

Most of our applications use some kind of presenter to build the objects needed. Occasionally we have inline ruby in the templates, but we (obviously) avoid doing that as much as possible.

What if the component has no dynamic content? Do you still use a presenter?Do you have an example you can show or an article about this?

We have a haml component that renders other components...
https://github.com/lonelyplanet/rizzo/blob/3b32170b217420d52ea83cd79b35fd25808d9153/app/views/layouts/examples/core.html.haml#L6

Ok for the style guide you can have configs in yaml files but where do keep real app component config hash? I understand using presenters when its decorating a specific object, but take the above example, this doesnt make sense in an object presenter i think. So what would be the best option here?
Could use the controller helper for that but it doesnt feels right either imho.
Do you have other suggestions?

@jcreamer898 did you have time to think about that?


Certificates should use "Provider = Microsoft RSA SChannel Cryptographic Provider" for Exchange compatibility

Current certificates cannot be used as Exchange Control Panel certificates. Quoting from https://blogs.technet.microsoft.com/jasonsla/2015/01/15/the-one-with-the-fba-redirect-loop/:

Exchange FBA does not support CNG certificates.  Exchange only uses and supports the legacy
CryptoAPI which uses Cryptographic Service Providers (CSP).

The workaround is to use the "Microsoft RSA SChannel Cryptographic Provider" when installing the certificate. According to the blog post this can be achieved in multiple ways:

Convert a given certificate, for example with OpenSSL:

openssl.exe pkcs12 -in old_certificate.pfx -out certificate.pem -nodes
openssl.exe pkcs12 -export -in certificate.pem -out new_certificate.pfx

Specify the provider when importing the cert:
certutil -csp "Microsoft RSA SChannel Cryptographic Provider" -importpfx <CertificateFilename>

This change would allow me to use the certificates for Exchange servers. Without the change, some parts of Exchange break in very non-obvious ways.

I currently tried Certify to generate my SSL cert, however, I'm running into the issue above as well.  I am searching for an ACME client that will automatically use the proper provider for Exchange so I don't have to have manual intervention all the time.  I figured I would ask that here just in case you found a solution as well.

Using the LetsEncrypt-Win-Simple Client allows OWA to work

Would be good if no manual changes to the certificate were needed, but I've got some question marks about this.

I'm not sure how to it from code (LEWS doesn't use the command line program), though perhaps with some more research I or someone else could figure that out.

I'm also not sure what the impact on other use cases would be. The documentation says that it supports SSL 3.0 and TLS 1.0, where it's kind of worrying for me that later versions of TLS are not listed.

https://msdn.microsoft.com/en-us/library/windows/desktop/aa386988(v=vs.85).aspx

Might this be solved with the option to provide your own CSR? (e.g. #165)?

No, the problem isn't with the certificate itself, the item modified by the -csp is a label on the PFX container file format. In fact the -CSP option can me moved to the second openssl command where it labels the PFX file itself as having been provided by the old Microsoft library.
As they stand the first openssl command extracts only the signed certificates and the key from the PFX file, it ignores all the additional Microsoft provided "****". The second openssl command creates a minimal PFX file with none of the labels or metadata about the certificates set. Neither of these commands can change anything in the certificate because that would break them. Especially they cannot change the public key, which is the only thing that a CA will use unchanged from the CSR.

I think this should come from upstream. @ebekker does all of this mean anything to you? :)

According to @rdebath, this is an issue with the way the PFX archive is exported.  With the current and latest version of ACMESharp, I've moved over to BouncyCastle as the main supported crypto provider (OpenSSL lib and CLI versions are still there if needed, but I'm not planning on supporting them going forward because they were brittle).
So the code to generate the PFX is here, so if there is some option that I need to provide to generate an Exchange-friendly PKCS12 archive, I'll be happy to include it, or at least make it optional.

Now, I'm not sure if this project has upgraded to the latest version of ACMESharp yet (0.9.x) but if not, then you may be working with the output of the OpenSSL CLI crypt provider, which was the previous default implementation.

Thanks for the feedback. It looks like LEWS is using a pretty dated version of ACMESharp (0.8.1), so it should be upgraded. The latest version on NuGet seems to be 0.8.5 though. Will 0.9.x appear there or would you recommend us to switch to MyGet?

I published the latest to nuget.org just a couple days ago, including some recent bug fixes.

I created a pull request with changes I believe would enable LEWS to support this without risk to other clients/applications. The code is mostly untested but should give you an idea of what would need to be done: https://github.com/ebekker/ACMESharp/pull/297

Fixed it in v1.9.7 in a bit of a hacky way outside of the ACMESharp library (opening and re-saving the PFX)

This is probably a dumb question, but does this issue being closed mean that the certificates produced by win-acme will now use the "Microsoft RSA SChannel Cryptographic Provider" provider?
Thanks in advance.

I can confirm on my exchange box with win-acme its using the RSA schannel provider as is needed for exchange. also don't run into the CU upgrade bug, make sure your exchange cert uses the new param for permissions on the private key:
--acl-fullcontrol "network service,administrators"


Add a CONTRIBUTING.md file to the repo

Add a CONTRIBUTING.md file with guidelines and instructions on how to contribute to the project.
Add the BURN_THE_CONTRIBUTOR_COVENANT_WITH_FIRE.md file to the repo to make it clear that we're not adopting it or any official code of conduct.

Resoved by #31


New Project In Place of COMING SOON!!

Describe the project
I want to add a new project in the place of coming soon.

The project is a job listing web app. The users also have the option to add new jobs. Users can also search jobs via country, state, job company, job requirements, etc.
I have built this project using only HTML , CSS and JavaScript. This is a great learning for people who thinks we can only add new jobs via backend technologies. This project helps in exceeding the limit of the developer and is a great learning project.
Please assign me this issue so that I can add this project and add my contribution to this community.

Create a fresh issue after 1st June


Fix default include tags for experimental mode

I presume this fixes the missing experimental brushes in experimental mode?

Yes. Sorry - that's not as clear as I meant it to be.

I wasn’t clear; I meant if it’s sufficient to resolve the issue. I’ve seen that the answer is yes :-)