Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for setting max current #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mbbush
Copy link

@mbbush mbbush commented Apr 6, 2021

Closes #10

@mbbush
Copy link
Author

mbbush commented Apr 17, 2021

@jesserockz I'd like to be able to use this code from home assistant. Could you merge and publish a new version if this looks good to you? I tested it on my system and it worked fine.

@jesserockz
Copy link
Owner

Hi @mbbush I didn't even get notified of this. Weird.

But I will take a look this week. Would you implement this on the HA side too?

@mbbush
Copy link
Author

mbbush commented Apr 18, 2021 via email

@jesserockz
Copy link
Owner

Just looking through the API doc in the repo, there is a better API call to set the charging limit

image

@mbbush
Copy link
Author

mbbush commented Apr 20, 2021

I saw that, and it was the first thing I tried. It was super helpful to have the api docs committed to the repo!

When I make that api call, at least on my hardware, I get a successful response, and if I immediately call the get_state endpoint, I see the result of the updated current. But within a few seconds (and before it actually changes the power usage as measured by an external meter), the change gets automatically reverted.

Example (timestamps are approximate):
Car is charging at 32A (max for my car). get_state command reports amps_limit = 40
At 12:00:00, issue set_limit command to set current to 15A. Get success response.
At 12:00:01, issue get_state command. Reports amps_limit = 15
At 12:00:05, issue get_state command. Reports amps_limit = 40
Looking at actual power consumption (from my Sense energy meter), current never actually changed from 32A.

The best explanation for this that I can think of is that the cloud api accepts the new limit, updates its internal state, then pushes the change to the charger, which rejects the update for some reason, causing the cloud to revert to the previous value. I haven't sniffed the network traffic of the actual juicebox to confirm this, though.

I don't know if this behavior is true of all juicenet chargers, or just mine. (a Juicebox 40 from 2019)

I actually mentioned that this was a weird implementation in a comment on line 98, although that probably could have been more clear.

Using the set_info command to update the amps_wire_limit field seems to match what happens when I make a similar update in the app, in the only way I've found to do this manually using the JuiceNet app. That's also how I found out that it wipes some of the other fields if you don't include them in the set_info command.

@jesserockz
Copy link
Owner

Ah, I see. I have not actually tried any of the commands in the API, including this as I only have an 8A JuiceCord from 2016, so I cannot limit it any lower without it just turning off. I understand why this would work though because of the wire limit, but strange that the set_limit does not work properly.

I do however know the traffic from the box to the cloud which is a UDP string that I have gone back to every now and then trying to reverse engineer the checksum so that I can get rid of the cloud connection altogether. I also contacted juicenet/enelx to ask for the algorithm but as I expected they said they would not help.

@jesserockz
Copy link
Owner

jesserockz commented Apr 21, 2021

I have just been playing around with this now and if I make the set_limit api call, I see the results between the cloud and charger instantly change to show its only allowed to have the specified amperage and it sticks too without reverting.

After setting it to 7 I see this in the response:

'charging': {'amps_limit': 7, 'amps_current': 6.4, 'voltage': 238, ...

Normally mine is set to 10A and charges at 7.4 amps

@mbbush
Copy link
Author

mbbush commented Apr 26, 2021

Hmm... That's certainly what I'd expect to happen, it's just not what happens on my charger (I double checked last weekend).

I can see several options here:

  • I contact enelx support to try to figure out why my charger is reverting the limit change
  • I set up a MITM for the traffic between the box and the cloud to see if that helps illuminate anything
  • I set up a MITM for the traffic from my phone to the cloud, and see what api commands the juicenet app is issuing. It seems like it's doing the set_info command, but I don't know for sure.
  • We leave the code as is and merge it because setting the limit using set_info works (and matches what the juicenet app seems to do)
  • You or I update the code to provide different methods for updating the info page vs setting the charging limit, at the cost of making the library's interface more confusing.
  • Add a configuration parameter when initializing the charger, that allows you to specify which means of setting current you want to use. Provide a default (I'm not sure which would be a better default).

I'm curious what you'd suggest. It's been a long time since I've set up a MITM for anything, and I think that it's gotten much more difficult to install custom root ssl certs on android since then, so if the app is using https, I may be out of luck. But it is something I've been wanting to play around with more.

I'd also welcome any suggestions for how to approach support on this, because I can easily see a conversation that starts with "when I manually make calls against your private api..." going nowhere.

@jesserockz
Copy link
Owner

The MITM on Android is how I initially created this library as I did not have the document at the time. I think yes, the android app sets only the wire amp limit using set_info as I have not found a screen that allows you to change it dynamically with the other method and I think that api function is more intended for mass control and/or controlling based on solar output etc like you want.

The MITM for the box to the cloud is easy as its a "simple" string sent via a UDP "connection" (I know UDP doesnt actually make a connection) .

Every second (almost) the cloud sends a string like CMD11032A10M10C217S261!46H$

11032 = 1 (Tuesday) 10:32am (My local time)
A10 = Amps the charger is allowed to charge (Becomes 0 based on time of use and the limit settings)
M10 = The Max amps the charger is allowed to charge - Always the limit including outside the time of use)
C217 and S261 = Random values that I have no clue about and chage to some random number in every message.
46H = Some sort of checksum

Message from box to cloud: ********:v7,s819,u59031,V2406,L9039973,S1,T36,M10,m20,t3,i43,e0,f5004,X0,Y0!1S4:

Expand
{
    "data": {
        "A": [
            0.1,
            "amps"
        ],
        "E": [
            0.001,
            "session_energy"
        ],
        "L": [
            0.001,
            "lifetime_energy"
        ],
        "M": [
            1,
            "max_current"
        ],
        "S": [
            [
                "Standby",
                "Plugged-In",
                "Charging"
            ],
            "status"
        ],
        "T": [
            1,
            "temperature"
        ],
        "V": [
            0.1,
            "voltage"
        ],
        "X": [
            1,
            "X"
        ],
        "Y": [
            1,
            "Y"
        ],
        "e": [
            1,
            "e"
        ],
        "f": [
            0.01,
            "frequency"
        ],
        "i": [
            1,
            "sequence"
        ],
        "m": [
            1,
            "m"
        ],
        "s": [
            1,
            "s"
        ],
        "p": [
            1,
            "p"
        ],
        "t": [
            1,
            "update_interval"
        ],
        "u": [
            0.01,
            "uptime"
        ],
        "v": [
            1,
            "v"
        ]
    },
    "custom": {
        "W": [
            "data.voltage * data.amps",
            "watts"
        ]
    }
}

@clarity-phev
Copy link

Gentlemen:

It has been a while since you posted this. I have been using this Juicenet API, but recently Enel-X has decided to abandon home.juice.net portal, and hence the account there and functionality of this API has ceased. This is very disappointing. They now only offer a new App 'JuicePass' (which sucks in my opinion). They have no plans to provide a new web interface, no plans for an API, and the new App lacks much of the telemetry that was previously available.

Because of all this, I have spent some time looking at the UDP packets (which seem to be sent like a heartbeat every 10 seconds from the Juicebox to the Mothership). They are 349 bytes long, and seem to be plain text, but I do NOT see the key telemetry within these messages (like Line Voltage, Current, Temperature, Power, and the like).

I just found your comments above about "Message from Box to Cloud". This is exactly what I am looking for...
Can you elaborate on how / where you see the messages that you show above, as you identified here:
**"Message from box to cloud: ******:v7,s819,u59031,V2406,L9039973,S1,T36,M10,m20,t3,i43,e0,f5004,X0,Y0!1S4:"

Are you aware of this transition to a 'new' system on the part of Enel-X?

@mbbush
Copy link
Author

mbbush commented Feb 27, 2023

I've seen the new app advertised, and I agree with you. It's a step backwards for users of their home charging products.

My home assistant integration and my "old" EV JuiceNet android app continue to work, at least so far, approximately as well as they always have, although with intermittent inexplicable failures or nonsensical behavior.

Getting a local API would be great. Based on the text based UDP comms, I think the first step would be getting a read only API that relies on MITMing the device. Then we could set up logging and get enough packets to hopefully reverse engineer the protocol and be able to send packets too.

If successful, we'd probably need to block most or all cloud traffic, which would disable some of the "smart grid" type features like demand response and charging on low carbon electricity. This has some significant downsides, at least for me, as I use and enjoy those features.

In theory, this would be possible, but I've never successfully done something like this before. I'm also likely to be getting a different EVSE soon, so my personal benefit from this project would be low.

@clarity-phev
Copy link

clarity-phev commented Feb 27, 2023 via email

@mbbush
Copy link
Author

mbbush commented Feb 27, 2023

I got that email on January 17, announcing the same Feb 20 cutover date.

@tomayac
Copy link

tomayac commented Apr 28, 2023

I started a reverse-engineering effort of the new Enel X Way API and have put my findings in a public Gist. Help is very much welcome! So far I have the endpoints, but need to understand authentication, potentially request signing, etc.

@clarity-phev
Copy link

Hello - If I am understanding you correctly, the API that you seek is already documented here:
https://github.com/jesserockz/python-juicenet

Look at the file - JuiceNet API_client_12_11_2017.docx

Enel X is dropping this however, and they have a new JuicePass App with no plans to support any kind of API going forward. If you get 'migrated' to the new servers you will lose access to this API.

Am I misunderstanding your objectives?

@tomayac
Copy link

tomayac commented Apr 28, 2023

My reverse-engineering attempt already looks at said new API. The old API's origin is https://jbv1-api.emotorwerks.com, whereas the new Enel X Way API's origin is https://emobility.enelx.com.

@clarity-phev
Copy link

Got it....
I think you are on the right track, but may be an uphill battle As you say, authentication, etc. may make this virtually impossible without cooperation from Enel X...

@mbbush
Copy link
Author

mbbush commented Jul 16, 2023

I'm still running just fine on the old version of the API. The only reason I can think of why they might not have migrated me is that I have a second charger on my account, which is a clipper creek model, and has an extremely intermittent internet connection.

I don't know which of those factors (more than one charger, third-party charger, device that won't update to latest firmware) is causing them to leave me on the old servers, but I'm still happily using this integration with no changes.

@clarity-phev
Copy link

just for reference, I struggled along with bugs for a couple of months in the new JuicePass application. Eventually EnelX tech support un-migrated me, and I am happily back to the original application and servers. It is unclear if / when they will eliminate the old setup but if you are unhappy with the new stuff, they will put you back upon request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow setting max current
4 participants